• Codeforces Round #441 Div. 2题解


      比赛的时候E调了好久...F没时间写T T

      A:直接走到短的路上来回走就好了

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    using namespace std;
    const int maxn=500010,inf=1e9;
    int n,a,b,c;
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    int main()
    {
        read(n);read(a);read(b);read(c);
        if(n==1)return puts("0"),0;
        int mn=min(a,min(b,c));int now=1;
        if(a==mn||b==mn)printf("%d
    ",mn*(n-1));
        else printf("%d
    ",min(a,b)+mn*(n-2));
    }
    View Code

      B:将所有数%m,找到最多的相同的数即可

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    using namespace std;
    const int maxn=500010,inf=1e9;
    int n,k,m,ans,ansi,cntt;
    int x[maxn],y[maxn];
    int v[maxn];
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    int main()
    {
        read(n);read(k);read(m);
        for(int i=1;i<=n;i++)read(x[i]),y[i]=x[i]%m;
        for(int i=1;i<=n;i++)
        {
            v[y[i]]++;
            if(v[y[i]]>ans)
            {
                ans=v[y[i]];
                ansi=y[i];
            }
        }
        if(ans>=k)
        {
            puts("Yes");
            for(int i=1;i<=n;i++)
            {
                if(y[i]==ansi)printf("%d ",x[i]),cntt++; 
                if(cntt==k)return 0;
            } 
         } 
         else puts("No");
    }
    View Code

      C:答案只可能在[n-100,n]之间,枚举一下就好

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    using namespace std;
    const int maxn=500010,inf=1e9;
    int n,cnt;
    int ans[maxn];
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    int main()
    {
        read(n);
        for(int i=max(1,n-100);i<=n;i++)
        {
            int x=i,sum=i;
            while(x)
            {
                sum+=x%10;
                x/=10;
            }
            if(sum==n)ans[++cnt]=i;
        }
        printf("%d
    ",cnt);
        for(int i=1;i<=cnt;i++)printf("%d ",ans[i]);
    }
    View Code

      D:最后连续的硬币删掉,前面还剩多少个硬币就是答案

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    using namespace std;
    const int maxn=500010,inf=1e9;
    int n,x;
    bool b[maxn];
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    int main()
    {
        puts("1");read(n);int N=n;
        for(int i=1;i<=n;i++)
        {
    //        printf("%dQAQ
    ",N);
            read(x);b[x]=1;
            while(b[N])N--;
            printf("%d ",i-(n-N)+1);
        }
    }
    View Code

      E:从每种数字可以改或者不改想到2-SAT,如果第i个字符串比第i+1个字符串小,v[i][j]和v[i+1][j]不一样,那么v[i+1][j]改,v[i][j]就必须改,v[i][j]不改,v[i+1][j]就不能改,如果第i个字符串比第i+1个字符串大,那么v[i][j]必须改,v[i+1][j]不能改,如上连边跑一个可行方案即可。

    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #include<map>
    #define ll long long 
    using namespace std;
    const int maxn=200010,inf=1e9;
    struct poi{int too,pre,x;}e[maxn<<2],e2[maxn<<2];
    int last[maxn],last2[maxn],dfn[maxn],low[maxn],col[maxn],lack[maxn],ru[maxn],rs[maxn],st[maxn],op[maxn];
    int n,m,x,y,z,tot,tot2,tott,top,color,flag,len,cnt;
    int ans[maxn];
    vector<int>v[maxn];
    void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    void add(int x,int y){e[++tot].too=y;e[tot].x=x;e[tot].pre=last[x];last[x]=tot;}
    void add2(int x,int y){e2[++tot2].too=y;e2[tot2].x=x;e2[tot2].pre=last2[x];last2[x]=tot2;}
    int next(int x){return x&1?x+1:x-1;}
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tott;st[++top]=x;lack[x]=top;
        for(int i=last[x];i;i=e[i].pre)
        if(!dfn[e[i].too])tarjan(e[i].too),low[x]=min(low[x],low[e[i].too]);
        else if(!col[e[i].too])low[x]=min(low[x],dfn[e[i].too]);
        if(dfn[x]==low[x])for(color++;top>=lack[x];top--)col[st[top]]=color;
    }
    void topsort()
    {
        top=0;for(int i=1;i<=color;i++)if(!ru[i])st[++top]=i;
        while(top)
        {
            int now=st[top--];
            if(!rs[now])rs[now]=1,rs[op[now]]=2;
            for(int i=last2[now];i;i=e2[i].pre)
            if(!(--ru[e2[i].too]))st[++top]=e2[i].too;
        }
    }
    int main()
    {
        read(n);read(m);
        for(int i=1;i<=n;i++)
        {
            read(len);
            for(int j=1;j<=len;j++)
            read(x),v[i].push_back(x); 
        }
        for(int i=1;i<n;i++)
        {
            int flagg=0;
            for(int j=0;j<min(v[i].size(),v[i+1].size());j++)
            if(v[i][j]!=v[i+1][j])
            {
                if(v[i][j]<v[i+1][j])add(next(v[i+1][j]<<1),next((v[i][j])<<1)),add(v[i][j]<<1,v[i+1][j]<<1);
                else add(v[i][j]<<1,next((v[i][j])<<1)),add(next((v[i+1][j])<<1),v[i+1][j]<<1);
                flagg=1;break; 
            }
            if(!flagg&&v[i].size()>v[i+1].size())return puts("No"),0;
    //        else add(next(v[i][min(v[i].size(),v[i+1].size())]<<1),next((v[i+1][min(v[i].size(),v[i+1].size())])<<1));
        }
        for(int i=1;i<=m<<1;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=m;i++)
        {
            if(col[i<<1]==col[next(i<<1)]){printf("No
    ");flag=1;break;}
            else op[col[i<<1]]=col[next(i<<1)],op[col[next(i<<1)]]=col[i<<1];
        }
        if(flag)return 0;
        for(int i=1;i<=tot;i++)if(col[e[i].x]!=col[e[i].too])add2(col[e[i].too],col[e[i].x]),ru[col[e[i].x]]++;
        topsort();
    //    for(int i=1;i<=tot;i++)printf("QAQ%d %d
    ",e[i].x,e[i].too);
        //if(rs[col[(i<<1)]]==rs[col[next(i<<1)]])return puts("No"),0;
        for(int i=1;i<=m;i++)if(rs[col[(i<<1)]]!=1)ans[++cnt]=i;
        printf("Yes
    %d
    ",cnt);
        for(int i=1;i<=cnt;i++)printf("%d ",ans[i]); 
        return 0;
    }
    View Code

      F:预处理出每个数每一位是0的那位左边最近的1和右边最近的1,用单调栈找出每个最大值所在的区间,统计答案即可。

      T T一开始只预处理了20位查了好久错,浅谈状压写多了的后果

    #include<iostream> 
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath> 
    #include<algorithm> 
    #define ll long long
    using namespace std;
    const int maxn=500010,inf=2e9;
    int n,top;
    int st[maxn],a[maxn],digit[maxn][32],pre[maxn][32],Pre[maxn],next[maxn][32],Next[maxn],cnt[maxn];
    ll ans;
    inline void read(int &k)
    {
        int f=1;k=0;char c=getchar();
        while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
        while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar();
        k*=f;
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;i++)
        {
            read(a[i]);
            for(int x=a[i];x;x>>=1)digit[i][++cnt[i]]=x&1;
        }
        for(int j=1,last=0;j<=30;j++,last=0)
        for(int i=1;i<=n;i++)
        {
            if(!digit[i][j])pre[i][j]=last;
            if(digit[i][j])last=i;
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=30;j++)
        if(!digit[i][j])
        Pre[i]=max(Pre[i],pre[i][j]);
        memset(next,32,sizeof(next));
        for(int j=1,last=n+1;j<=30;j++,last=n+1)
        for(int i=n;i;i--)
        {
            if(!digit[i][j])next[i][j]=last;
            if(digit[i][j])last=i;
        }
        memset(Next,32,sizeof(Next));
        for(int i=1;i<=n;i++)
        for(int j=1;j<=30;j++)
        if(!digit[i][j])
        Next[i]=min(Next[i],next[i][j]);
        a[++n]=inf;
        for(int i=1;i<=n;i++)
        {
            for(;top&&a[i]>=a[st[top]];top--)
            {
                ans+=1ll*((i-1)-st[top]+1)*(st[top]-(st[top-1]+1)+1);
                ans-=1ll*(1ll*st[top]-1ll*max(st[top-1]+1,Pre[st[top]]+1)+1)*(min(i-1,Next[st[top]]-1)-st[top]+1);
            }
            st[++top]=i;
        }
        printf("%lld
    ",ans);
    }
    View Code
  • 相关阅读:
    杜教筛刷题总结
    后缀自动机刷题总结
    回文自动机刷题总结
    后缀数组刷题总结
    LCT刷题总结
    省选模拟一题解
    FFT/NTT中档题总结
    二项式反演总结
    JS只能输入数字,数字和字母等的正则表达式
    jquery 条件搜索某个标签下的子标签
  • 原文地址:https://www.cnblogs.com/Sakits/p/7681051.html
Copyright © 2020-2023  润新知