Educational Codeforces Round 55 Div. 2 翻车记

  A:签到。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int T;
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    T=read();
    while (T--)
    {
        int n=read(),x=read(),y=read(),d=read();
        if (abs(y-x)%d==0) cout<<abs(y-x)/d<<endl;
        else
        {
            int ans=2000000000;
            if ((y-1)%d==0) ans=min(ans,(y-1)/d+(x-2)/d+1);
            if ((n-y)%d==0) ans=min(ans,(n-y)/d+(n-x-1)/d+1);
            if (ans==2000000000) cout<<-1<<endl;
            else cout<<ans<<endl;
        }
    }
    return 0;
}
View Code

  B:讨论了好多种情况写的老长交了五发30min的时候才过心态爆炸。随便怎么做都行。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010 
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,a[N],pre[N],suf[N],ans,cnt;
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    n=read();
    for (int i=1;i<=n;i++) cnt+=(a[i]=getc()=='S');
    int x=0;
    for (int i=1;i<=n;i++)
    {
        pre[i]=x;
        if (a[i]) x=i;
    }
    x=n+1;
    for (int i=n;i>=1;i--)
    {
        suf[i]=x;
        if (a[i]) x=i;
    }
    int flag=0;
    for (int i=1;i<=n;i++)
    if (a[i]==0)
    {
        int t=i;while (t<n&&a[t+1]==a[i]) t++;
        flag++;
        i=t;
    }
    if (flag==0) {cout<<0;return 0;}
    if (flag==1)
    for (int i=1;i<=n;i++)
    if (a[i]==0)
    {
        int t=i;while (t<n&&a[t+1]==a[i]) t++;
        cout<<t-i+1;return 0;
    }
    for (int i=1;i<=n;i++)
    if (pre[i]!=i-1&&suf[i]!=i+1) ans=max(ans,suf[i]-pre[i]-1);
    if (flag<=2) ans--;
    if (flag>=2)
    for (int i=1;i<=n;i++)
    {
        if (pre[i]==i-1) ans=max(ans,suf[i]-i);
        if (suf[i]==i+1) ans=max(ans,i-pre[i]);
    }
    if (cnt==0) ans=n;
    cout<<max(0,ans)<<endl;
    return 0;
}
View Code

  C:对于每个科目显然应该从大到小选。枚举各科的学生人数,考虑每个科目,只要能选该科的人数足够且价值>0就应该把这些人选进去。用链表维护哪些科目是应该选的即可,只要人数不够或者价值<=0就将其从中删除。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define N 200010 
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,ans,cnt,tot[N],cho[N],nxt[N],pre[N];
vector<int> a[N];
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    n=read(),m=read();
    for (int i=1;i<=n;i++)
    {
        int x=read(),y=read();
        a[x].push_back(y);tot[x]++;
    }
    for (int i=1;i<=m;i++) sort(a[i].begin(),a[i].end()),reverse(a[i].begin(),a[i].end());
    for (int i=0;i<=m;i++) nxt[i]=i+1,pre[i+1]=i;
    for (int j=1;j<=n;j++)
    {
        int x=nxt[0];
        while (x!=m+1)
        {
            if (tot[x]>=0)
            {
                if (tot[x]==0) nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x],cnt-=cho[x],tot[x]=-1;
                else
                {
                    tot[x]--,cnt+=a[x][j-1],cho[x]+=a[x][j-1];
                    if (cho[x]<=0) nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x],cnt-=cho[x],tot[x]=-1;
                }
            }
            x=nxt[x];
        }
        ans=max(ans,cnt);
    }
    cout<<ans;
    return 0;
}
View Code

  D:显然应该尽量让他形成一条链。只有度数<=1的点会对其造成影响。在链的两端至少各放一个度数<=1的点并将主链连起来然后瞎连即可。讨论一下一些特殊情况。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 510
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,a[N],b[N],cnt,t;
bool flag[N];
struct data{int x,y;
}edge[N];
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    n=read();
    for (int i=1;i<=n;i++)
    {
        a[i]=read();
        if (a[i]==1) b[++cnt]=i;
        else flag[i]=1;
    }
    if (cnt==0)
    {
        cout<<"YES"<<' '<<n-1<<endl;
        cout<<n-1<<endl;
        for (int i=1;i<n;i++) cout<<i<<' '<<i+1<<endl;
        return 0;
    }
    if (cnt==1)
    {
        if (b[1]==1)
        {
            cout<<"YES"<<' '<<n-1<<endl;
            cout<<n-1<<endl;
            for (int i=1;i<n;i++) cout<<i<<' '<<i+1<<endl;
        }
        else
        {
            cout<<"YES"<<' '<<n-1<<endl;
            cout<<n-1<<endl;
            for (int i=1;i<b[1]-1;i++) cout<<i<<' '<<i+1<<endl;
            cout<<1<<' '<<b[1]<<endl;
            for (int i=b[1];i<n;i++) cout<<i<<' '<<i+1<<endl; 
        }
        return 0;
    }
    if (n==2&&cnt==2) {cout<<"YES"<<' '<<1<<endl<<1<<endl<<1<<' '<<2;return 0;}
    for (int i=1;i<=n;i++)
    if (a[i]!=1) {edge[++t].x=b[1],edge[t].y=i;break;}
    if (t==0) {cout<<"NO";return 0;}
    for (int i=n;i>=1;i--)
    if (a[i]!=1) {edge[++t].x=b[cnt],edge[t].y=i;break;}
    if (t==1) {cout<<"NO";return 0;}
    int x=2;cnt--;
    for (int i=1;i<=n;i++)
    while (a[i]>2&&x<=cnt) edge[++t].x=b[x++],edge[t].y=i,a[i]--;
    for (int i=1;i<=n;i++)
    if (flag[i])
        for (int j=i-1;j>=1;j--)
        if (flag[j]) {edge[++t].x=i,edge[t].y=j;break;}
    if (t<n-1) cout<<"NO";
    else
    {
        cout<<"YES"<<' '<<n-cnt<<endl;
        cout<<n-1<<endl;
        for (int i=1;i<n;i++) cout<<edge[i].x<<' '<<edge[i].y<<endl;
    }
    return 0;
}
View Code

  E:先把本来就和C相同的数数出来做个前缀和。显然让所选区间的左右端点变为与C相同是不会更劣的。考虑每一种数。假设固定了左端点,右端点不断向右扩展,那么遇到与左端点相同的数就可以使答案+1,遇到本身就与C相同的数则会使答案-1。于是将对该数每一段的价值取出来,形如1 -a1 1 -a2 1……,做个最大子段和就可以了。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 2000010
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,a[N],p[N],sum[N],nxt[N],b[N],t,cnt,ans;
int main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    n=read(),m=read();
    for (int i=1;i<=n;i++)
    {
        a[i]=read()-m+1000000;
        if (a[i]==1000000) cnt++;
    }
    for (int i=1;i<=n;i++) nxt[i]=p[a[i]],p[a[i]]=i;
    for (int i=1;i<=n;i++) sum[i]=sum[i-1]+(a[i]==1000000);
    ans=cnt;
    for (int i=0;i<=2000000;i++)
    if (i!=1000000&&p[i])
    {
        int x=p[i];t=0;b[++t]=1;
        while (nxt[x])
        {
            b[++t]=sum[nxt[x]]-sum[x];
            b[++t]=1;
            x=nxt[x];
        }
        int s=0;
        for (int j=1;j<=t;j++)
        {
            s+=b[j];
            if (s<0) s=0;
            ans=max(ans,cnt+s);
        }
    }
    cout<<ans<<endl;
    return 0;
}
View Code

  F:没看

  G:最大权闭合子图裸题。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define int long long
#define N 2010 
#define M 10010
#define S 0
#define T 2001
#define inf 10000000000000ll
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,p[N],a[N],t=-1,d[M],cur[M],q[M],ans;
struct data{int to,nxt,cap,flow;
}edge[M<<3];
void addedge(int x,int y,int z)
{
    t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=0,p[x]=t;
    t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,p[y]=t;
}
bool bfs()
{
    memset(d,255,sizeof(d));d[S]=0;
    int head=0,tail=1;q[1]=S;
    do
    {
        int x=q[++head];
        for (int i=p[x];~i;i=edge[i].nxt)
        if (d[edge[i].to]==-1&&edge[i].flow<edge[i].cap)
        {
            q[++tail]=edge[i].to;
            d[edge[i].to]=d[x]+1;
        }
    }while (head<tail);
    return ~d[T];
}
int work(int k,int f) 
{
    if (k==T) return f;
    int used=0;
    for (int i=cur[k];~i;i=edge[i].nxt)
    if (d[k]+1==d[edge[i].to])
    {
        int w=work(edge[i].to,min(f-used,edge[i].cap-edge[i].flow));
        edge[i].flow+=w,edge[i^1].flow-=w;
        if (edge[i].flow<edge[i].cap) cur[k]=i;
        used+=w;if (used==f) return f;
    }
    if (used==0) d[k]=-1;
    return used;
}
void dinic()
{
    while (bfs())
    {
        memcpy(cur,p,sizeof(p));
        ans-=work(S,inf);
    }
}
signed main()
{
/*#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif*/
    n=read(),m=read();
    for (int i=1;i<=n;i++) a[i]=read();
    memset(p,255,sizeof(p));
    for (int i=1;i<=m;i++)
    {
        int x=read(),y=read(),z=read();
        addedge(n+i,x,inf),addedge(n+i,y,inf);
        addedge(S,n+i,z);ans+=z;
    }
    for (int i=1;i<=n;i++) addedge(i,T,a[i]);
    dinic();
    cout<<ans;
    return 0;
}
View Code

  

  小号打的。result: rank 34 rating +158

原文地址:https://www.cnblogs.com/Gloid/p/10040398.html