zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 24

    陷入了一种每场比赛打完都不想改题的虚无状态,不能这样,改题改题改题。
    昨晚只写了三道题意即题解的题…感觉意识模糊,看了看是unrated就睡了
    CF已经连续三场unrated了qwq,我一共就没打过几场
    A. Diplomas and Certificates
    题意:拿到certificate的人数将会是拿到diploma人数的k倍,但拿到他们的总人数不能超过n/2
    把n/2向下取底分成k+1分
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    typedef long long LL;
    LL n,k;
    int main()
    {
        scanf("%I64d%I64d",&n,&k);
        LL t1=n/2/(k+1),t2=t1*k;
        printf("%I64d %I64d %I64d
    ",t1,t2,n-t1-t2);
        return 0;
    }
    B. Permutation Game
    题意:给出一个排列a1...an,进行m轮游戏,首先选定一个leader作为l[1],l[i+1]=a[l[i]]+l[i]
    a[l[i]]+l[i]=l[i+1] 所以 a[l[i]]=l[i+1]-l[i]
    如果遇到有冲突的情况特判一下输出-1(一个以上的位置是同一个数或同一个位置几次得到的结果不一样)
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    using namespace std;
    int n,m,l[105],a[105];
    int num[105];
    vector<int>v;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        scanf("%d",&l[i]);
        for(int i=1;i<m;i++)
        {
            int t=l[i+1];
            while(t<=l[i])t+=n;
            if(a[l[i]]&&a[l[i]]!=t-l[i]){printf("-1
    ");return 0;}
            if(!a[l[i]])
            {
                a[l[i]]=t-l[i];
                num[a[l[i]]]++;
            }
        }
        for(int i=1;i<=n;i++)
        if(num[i]>1){printf("-1
    ");return 0;}
        else if(!num[i])v.push_back(i);
        for(int i=1;i<=n;i++)
        {
            if(!a[i])a[i]=v.back(),v.pop_back();
            printf("%d ",a[i]);
        }
        return 0;
    }
    C. Sofa Thief
    题意:有d个沙发,每个沙发占据相邻两个格子,定义一个沙发A在另一个沙发B左边为:存在沙发A的格子a和沙发B的格子b使得xa<xb,求出一个沙发满足给出的cntl,cntr,cntt,cntb
    m和n都不超过1e5,直接处理出前缀和,O(n)可求
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    struct data
    {
        int x1,y1,x2,y2;
    }sofa[100005];
    int d,n,m,cntl,cntr,cntt,cntb,xl[100005],yl[100005],xr[100005],yr[100005];
    int main()
    {
        scanf("%d%d%d",&d,&n,&m);
        for(int i=1;i<=d;i++)
        {    
            scanf("%d%d%d%d",&sofa[i].x1,&sofa[i].y1,&sofa[i].x2,&sofa[i].y2);
            xl[min(sofa[i].x1,sofa[i].x2)]++;
            yl[min(sofa[i].y1,sofa[i].y2)]++;
            xr[max(sofa[i].x1,sofa[i].x2)]++;
            yr[max(sofa[i].y1,sofa[i].y2)]++;
        }
        scanf("%d%d%d%d",&cntl,&cntr,&cntt,&cntb);
        for(int i=1;i<=n;i++)xl[i]+=xl[i-1];
        for(int i=1;i<=m;i++)yl[i]+=yl[i-1];
        for(int i=n;i;i--)xr[i]+=xr[i+1];
        for(int i=m;i;i--)yr[i]+=yr[i+1]; 
        for(int i=1;i<=d;i++)
        {
            int l=xl[max(sofa[i].x1,sofa[i].x2)-1];
            int r=xr[min(sofa[i].x1,sofa[i].x2)+1];
            if(sofa[i].x1!=sofa[i].x2)l--,r--;
            int t=yl[max(sofa[i].y1,sofa[i].y2)-1];
            int b=yr[min(sofa[i].y1,sofa[i].y2)+1];
            if(sofa[i].y1!=sofa[i].y2)t--,b--;
            if(l==cntl&&r==cntr&&t==cntt&&b==cntb)
            {printf("%d
    ",i);return 0;}
        }
        printf("-1
    ");
        return 0;
    } 
    D. Multicolored Cars
    题意:有n辆车依次驶过,给定对方选择的一个颜色a,请你选择一个颜色b使得在任一时刻cntb>=cnta
    感觉也没什么好说的,线性扫一遍即可,细节的话还是看代码
    (Update:发现被hack了,因为答案不能超出1000000…已改。)
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    using namespace std;
    int n,a,b,num[1000005],x[1000005];
    bool f[1000005];
    int main()
    {
        scanf("%d%d",&n,&a);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x[i]);
            if(a!=x[i]&&num[x[i]]<num[a])
            f[x[i]]=1;
            num[x[i]]++;
            if(a!=x[i]&&num[x[i]]<num[a])
            f[x[i]]=1;
        }
        if(!num[a]){printf("%d
    ",a+1<=1000000?a+1:a-1);return 0;}
        for(int i=1;i<=n;i++)
        {
            if(a!=x[i]&&num[x[i]]<num[a])f[x[i]]=1;
            if(!f[x[i]]&&x[i]!=a){printf("%d
    ",x[i]);return 0;}
        }
        printf("-1
    ");
        return 0;
    }
    E. Card Game Again
    题意:有多少连续的ai...aj的乘积是k的倍数
    将k分解质因数,处理出序列每个质因数个数的前缀和,对于每个左端点通过二分来得到最小的能使乘积为k的倍数的右端点
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    typedef long long LL;
    using namespace std;
    LL n,k,a[100005],cnt=0,num[50],sum[50][100005],res=0;
    LL read()
    {
        LL 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*10+c-'0';c=getchar();}
        return x*f;
    }
    bool check(int x,int y)
    {
        for(int i=1;i<=cnt;i++)
        if(x!=1&&sum[i][y]-sum[i][x-1]<sum[i][0])return false;
        else if(x==1&&sum[i][y]<sum[i][0])return false;
        return true;
    }
    int main()
    {
        n=read(),k=read();
        LL t=k;
        for(int i=2;i*i<=t;i++)
        {
            if(t%i==0)
            {
                num[++cnt]=i;
                while(t%i==0)
                t/=i,sum[cnt][0]++;
            }
        }
        if(t>1)num[++cnt]=t,sum[cnt][0]++;
        for(int i=1;i<=n;i++)
        {
            a[i]=read();
            int t=a[i];
            for(int j=1;j<=cnt;j++)
            {
                if(t%num[j]==0)
                {
                    while(t%num[j]==0)
                    t/=num[j],sum[j][i]++;
                }
            }
        }
        for(int i=1;i<=cnt;i++)
        for(int j=1;j<=n;j++)
        if(j!=1)sum[i][j]+=sum[i][j-1];
        for(int i=1;i<=n;i++)
        {
            int l=i,r=n,ans=-1;
            while(l<=r)
            {
                int mid=(l+r)>>1;
                if(check(i,mid))r=mid-1,ans=mid;
                else l=mid+1;
            }
            if(ans!=-1)res+=n-ans+1;
        }
        printf("%I64d
    ",res);
        return 0;
    }
    F. Level Generation
    题意:n个点的图,桥的个数要求不小于边数的一半,问边数的最大值
    n个点中k个点两两相连有k*(k-1)/2条边,其余的点顺次相连为桥n-k条边,当k*(k-1)/2<=n-k时才符合要求
    可以发现f(k)=n-k+min(n-k,k*(k-1)/2)是一个单峰函数,于是三分得到答案
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    using namespace std;
    typedef long long LL;
    LL q,n,ans;
    LL check(LL x)
    {
        if(x*(x-1)/2<=n-x){ans=max(ans,x*(x-1)/2+n-x);return x*(x-1)/2+n-x;}
        ans=max(ans,(n-x)*2);return (n-x)*2;
    }
    int main()
    {
        scanf("%I64d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%I64d",&n);
            LL l=1,r=n;
            ans=n-1;
            while(l+2<r)
            {
                int x1=l+(r-l)/3,x2=l+(r-l)*2/3;
                if(check(x1)<check(x2))l=x1;
                else r=x2;
            }
            for(int i=l;i<=r;i++)check(i);
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    G. Four Melodies
    题意:给出序列a1...an,找出四个不可重复的子序列使得子序列里相邻元素相差1或在模7意义下相等,最大化这四个子序列的长度和
    费用流。拆点建图还是比较容易的,然而边太多了需要优化…
    发现只需要找出4个子序列,所以模数相同时最多只需要向后连最近的4条边即可,对结果不会有影响
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<queue>
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,ss,s,t,a[6005],head[6005],cnt=0,vis[100005],f[6005],dis[6005],pre[6005];
    bool inq[6005];
    struct Node
    {
        int next,to,cap,w;
    }Edges[10000005];
    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*10+c-'0';c=getchar();}
        return x*f;
    }
    void addedge(int u,int v,int c,int w)
    {
        Edges[cnt].next=head[u];
        head[u]=cnt;
        Edges[cnt].to=v;
        Edges[cnt].cap=c;
        Edges[cnt++].w=w;
    }
    void insert(int u,int v,int c,int w)
    {
        addedge(u,v,c,w);
        addedge(v,u,0,-w);
    }
    queue<int>q;
    int MCMF()
    {
        int flow=0,cost=0;
        while(1)
        {
            memset(dis,-1,sizeof(dis));
            q.push(ss);
            inq[ss]=1,dis[ss]=0,f[ss]=INF,pre[ss]=-1;
            while(!q.empty())
            {
                int u=q.front();
                q.pop(),inq[u]=0;
                for(int i=head[u];~i;i=Edges[i].next)
                {
                    int v=Edges[i].to;
                    if(dis[v]<dis[u]+Edges[i].w&&Edges[i].cap>0)
                    {
                        dis[v]=dis[u]+Edges[i].w;
                        f[v]=min(f[u],Edges[i].cap);
                        pre[v]=i;
                        if(!inq[v])inq[v]=1,q.push(v);
                    }
                }
            } 
            if(dis[t]==-1)break;
            flow+=f[t];
            cost+=dis[t]*f[t];
            int p=t;
            while(pre[p]!=-1)
            {
                Edges[pre[p]].cap-=f[t];
                Edges[pre[p]^1].cap+=f[t];
                p=Edges[pre[p]^1].to;
            }
        }
        return cost;
    }
    int main()
    {
        memset(head,-1,sizeof(head));
        n=read(),ss=2*n+2,s=0,t=2*n+1;
        insert(ss,s,4,0);
        for(int i=1;i<=n;i++)
        {
            a[i]=read(),insert(i,i+n,1,1);
            insert(s,i,1,0),insert(i+n,t,1,0);
        }
        for(int i=1;i<=n;i++)
        {
            int have=0;
            for(int j=i+1;j<=n;j++)
            {
                if(abs(a[i]-a[j])==1&&vis[a[j]]!=i)
                insert(i+n,j,1,0),vis[a[j]]=i;
                else if(have<4&&vis[a[j]]!=i&&a[i]%7==a[j]%7)
                insert(i+n,j,1,0),have++,vis[a[j]]!=i;
            }
        }
        printf("%d
    ",MCMF());
        return 0;
    }
  • 相关阅读:
    使用Python对MySQL数据库操作
    使用Python对SQLite数据库操作
    使用Python对Access读写操作
    使用Python对Excel进行读写操作
    C# Serialization performance in System.Runtime.Serialization.Formatters.Binary.BinaryFormatter,Newtonsoft.Json.JsonConvert and System.Text.Json.JsonSerializer.Serialize
    C# calculate disk size
    C# rename files
    C# copy files from source directory to destination file and rename repeated files and does not override
    C# event
    C# redis StackExchange
  • 原文地址:https://www.cnblogs.com/Zars19/p/7098483.html
Copyright © 2011-2022 走看看