• Codeforces Round #517 Div. 1翻车记


      A:真的懵逼了。冷静了半天之后决定二分一下答案,然后先a安排上尽量小的再贪心地一个个扩大。40min才过。这个做法非常怂的以代码复杂度和时间复杂度为代价换取了比较稳的正确性,事实上由于1~n可以组合出1~n*(n+1)/2的所有数,只要从大到小贪心地放就可以了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    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,b,ans,ansa[1000000],ansb[1000000],cnta,cntb;
    bool flag[1000000];
    bool check(int k)
    {
        int w=a;cnta=cntb=0;
        for (int i=1;i<=k;i++)
        if (w>=i) ansa[++cnta]=i,w-=i;
        else break;
        ansa[cnta+1]=k+1;
        for (int i=cnta;i>=1;i--)
        {
            if (!w) break;
            while (w&&ansa[i]+1<ansa[i+1]) ansa[i]++,w--;
        }
        if (b>=1ll*k*(k+1)/2-(a-w)) return 1;
        else return 0;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    #endif
        a=read(),b=read();
        n=sqrt((a+b)*2ll)+2;
        int l=0,r=n;
        while (l<=r)
        {
            int mid=l+r>>1;
            if (check(mid)) ans=mid,l=mid+1;
            else r=mid-1;
        }
        int w=a;cnta=cntb=0;
        for (int i=1;i<=ans;i++)
        if (w>=i) ansa[++cnta]=i,w-=i;
        else break;
        ansa[cnta+1]=ans+1;
        for (int i=cnta;i>=1;i--)
        {
            if (!w) break;
            while (w&&ansa[i]+1<ansa[i+1]) ansa[i]++,w--;
        }
        printf("%d
    ",cnta);
        for (int i=1;i<=cnta;i++) printf("%d ",ansa[i]),flag[ansa[i]]=1;
        cout<<endl;
        printf("%d
    ",ans-cnta);
        for (int i=1;i<=ans;i++)
        if (!flag[i]) printf("%d ",i);
        return 0;
    }
    View Code

      B:首先对于修改字母显然要找到一个离左上角尽量远的可以将这段路径都改为a的点。这样可能是斜的一排点。然后考虑怎么使字典序最小,类似bfs的每次考虑斜的一排点,如果他可以由一个可能在答案中的点走来并成为最优解就给他标记上,最后由终点倒序输出即可。花了50min。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    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;
    }
    #define N 2010
    int n,m,a[N][N],f[N][N],ans[N*2],cnt=0;
    bool flag[N][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++)
            for (int j=1;j<=n;j++)
            {
                char c=getchar();
                while (c<'a'||c>'z') c=getchar();
                a[i][j]=c-'a'+1;
            }
        for (int i=0;i<=n;i++) f[0][i]=f[i][0]=n*n;
        for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
            if (i==1&&j==1) f[i][j]=a[i][j]!=1;
            else f[i][j]=min(f[i-1][j],f[i][j-1])+(a[i][j]!=1);
        int step=-1;
        for (int k=2*n-1;k>=0;k--)
        {
            for (int i=1;i<=n;i++)
            {
                int j=k-i+2;
                if (1<=j&&j<=n&&f[i][j]<=m) {step=k;flag[i][j]=1;}
            }
            if (step!=-1) break;
        }
        for (int i=1;i<=step+1;i++) putchar('a');
        flag[0][1]=1;
        for (int k=step+1;k<=2*n-1;k++)
        {
            int c=27;
            for (int i=1;i<=n;i++)
            {
                int j=k-i+2;
                if (1<=j&&j<=n&&(flag[i-1][j]||flag[i][j-1])) c=min(c,a[i][j]);
            }
            for (int i=1;i<=n;i++)
            {
                int j=k-i+2;
                if (1<=j&&j<=n&&(flag[i-1][j]||flag[i][j-1])&&a[i][j]==c) flag[i][j]=1;
            }
        }
        /*for (int i=1;i<=n;i++)
        {
            for (int j=1;j<=n;j++)
            cout<<flag[i][j]<<' ';
            cout<<endl;
        }*/
        int x=n,y=n;
        while (x-1+y-1>step)
        {
            ans[++cnt]=a[x][y];
            if (flag[x-1][y]) x--;
            else y--;
        }
        for (int i=cnt;i>=1;i--) putchar(ans[i]+'a'-1);
        return 0;
    }
    View Code

      然后就弃疗了。

      result:rank 227 rating +6 稳定的没救了。

  • 相关阅读:
    [poj2778]DNA Sequence(AC自动机+矩阵快速幂)
    密码学学习笔记
    [hdu3695]Computer Virus on Planet Pandora(AC自动机)
    [hdu1277]全文检索(AC自动机)
    [hdu3065]病毒侵袭持续中(AC自动机)
    [hdu2896]病毒侵袭(AC自动机)
    lintcode-84-落单的数 III
    lintcode-83-落单的数 II
    lintcode-79-最长公共子串
    lintcode-78-最长公共前缀
  • 原文地址:https://www.cnblogs.com/Gloid/p/9826310.html
Copyright © 2020-2023  润新知