【Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2)】 A.B.C.D

前言

在晚上的div2之前打开的这场,但是自己头脑貌似不太清醒,全程在写bug,而且B题不知道自己在写啥,写了一百多行?,C也写了好多bug导致最后的D一眼思路但是没写完。希望晚上状态不要这么差!QWQ


A. Golden Plate

题意

给你一个h*w的长方形边框,每减小一次h-=4,w-=4,问从当前大小减小k-1次,
总的周长是多少

做法

直接模拟

代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
int vis[105];
int vis2[105];
int main()
{
    int n,x,y;
    scanf("%d",&n);
    scanf("%d",&x);
    while(x--)
    {
        scanf("%d",&y);
        vis[y]=1;
    }
    for(int i=1;i<=n-1;i++)
    {
        scanf("%d",&x);
        for(int j=1;j<=100;j++) vis2[j]=0;
        while(x--)
        {
            scanf("%d",&y);
            vis2[y]=1;
        }
        for(int j=1;j<=100;j++)
        {
            if(vis[j]&&vis2[j]) vis[j]=1;
            else vis[j]=0;
        }
    }
    for(int i=1;i<=100;i++) if(vis[i]) printf("%d ",i);
    printf("\n");
    return 0;
}


B. Curiosity Has No Limits

题意

题意就是给你一个A序列和一个B序列
让你构造一个t序列,t序列满足
a i = t i t i + 1 a_i=t_i|t_{i+1}
b i = t i b_i=t_i & t i + 1 t_{i+1}

做法

赛中自己没什么想法,于是就写了个dp
dp[i][j]表示第i个位置放j是否合法,之后就暴力跑就可以了

代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5+5;
int dp[maxn][4];
int pre[maxn][4];
int t[maxn];
int a[maxn],b[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n-1;i++) scanf("%d",&b[i]);
    for(int i=0;i<=3;i++) dp[1][i]=1;
    int flag=0;
    for(int i=2;i<=n;i++)
    {
        if(a[i-1]==0)
        {
            if(b[i-1]==0)
            {
                if(dp[i-1][0])
                {
                    pre[i][0]=0;
                    dp[i][0]=1;
                }
            }
            else
            {
                flag=1;
                break;
            }
        }
        else if(a[i-1]==1)
        {
            if(b[i-1]==2||b[i-1]==3)
            {
                flag=1;
                break;
            }
            else if(b[i-1]==0)
            {
                if(dp[i-1][0])
                {
                    pre[i][1]=0;
                    dp[i][1]=1;
                }
                if(dp[i-1][1])
                {
                    pre[i][0]=1;
                    dp[i][0]=1;
                }
            }
            else
            {
                if(dp[i-1][1])
                {
                    pre[i][1]=1;
                    dp[i][1]=1;
                }
            }
        }
        else if(a[i-1]==2)
        {
            if(b[i-1]==1||b[i-1]==3)
            {
                flag=1;
                break;
            }
            else if(b[i-1]==0)
            {
                if(dp[i-1][0])
                {
                    pre[i][2]=0;
                    dp[i][2]=1;
                }
                if(dp[i-1][2])
                {
                    pre[i][0]=2;
                    dp[i][0]=1;
                }
            }
            else
            {
                 if(dp[i-1][2])
                 {
                     pre[i][2]=2;
                     dp[i][2]=1;
                 }
            }
        }
        else
        {
            if(b[i-1]==0)
            {
                if(dp[i-1][0])
                {
                    pre[i][3]=0;
                    dp[i][3]=1;
                }
                if(dp[i-1][1])
                {
                    pre[i][2]=1;
                    dp[i][2]=1;
                }
                if(dp[i-1][2])
                {
                    pre[i][1]=2;
                    dp[i][1]=1;
                }
                if(dp[i-1][3])
                {
                    pre[i][0]=3;
                    dp[i][0]=1;
                }
            }
            else if(b[i-1]==1)
            {
                if(dp[i-1][1])
                {
                    pre[i][3]=1;
                    dp[i][3]=1;
                }
                if(dp[i-1][3])
                {
                    pre[i][1]=3;
                    dp[i][1]=1;
                }
            }
            else if(b[i-1]==2)
            {
                if(dp[i-1][2])
                {
                    pre[i][3]=2;
                    dp[i][3]=1;
                }
                if(dp[i-1][3])
                {
                    pre[i][2]=3;
                    dp[i][2]=1;
                }
            }
            else
            {
                if(dp[i-1][3])
                {
                    pre[i][3]=3;
                    dp[i][3]=1;
                }
            }
        }
    }
    int tt=0;
    for(int i=0;i<=3;i++)
    {
        if(dp[n][i]) tt=1;
    }
    if(flag==1||tt==0)
    {
        printf("NO\n");
        return 0;
    }
    else
    {
        for(int i=0;i<=3;i++)
        {
            if(dp[n][i]) t[n]=i;
        }
        for(int i=n-1;i>=1;i--)
        {
            t[i]=pre[i+1][t[i+1]];
        }
        printf("YES\n");
        for(int i=1;i<=n;i++) printf("%d ",t[i]);
    }
    return 0;
}


C. Cram Time

题意

给你两个数a,b,用a,b分别构造两个序列A,B,
要求A序列的和小于a,B序列的和小于b
而且A序列中和B序列中每个数最多在两个序列中出现一次
要是最终的两个序列的长度和最大,输出两个序列

做法

a + b 1 + 2 + 3 + . . . + n 判断出a+b能够造的的最大的1+2+3+...+n
如果a+b>=(1+2+3+…n),一定可以构造出(1+2+3+…n)
至于构造方法,就先用a,b中大的数从大到小选,再用小的从大到小选,就OK了!

代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn = 1e5+5;
ll a,b;
vector<int> v1,v2;
int vis[maxn];
int main()
{
    scanf("%lld%lld",&a,&b);
    ll sum=a+b;
    ll pos=0;
    for(ll i=0;;i++)
    {
        if((1LL*i*(i+1))/2==sum)
        {
            pos=i;
            break;
        }
        else if((1LL*i*(i+1))/2>sum)
        {
            pos=i-1;
            break;
        }
    }
    ll maxx=max(a,b);
    ll minn=min(a,b);
    ll tmp=sum-(1LL*pos*(pos+1))/2;
    for(int i=pos;i>=1;i--)
    {
        if(maxx>=i)
        {
            v1.push_back(i);
            maxx-=(i);
            vis[i]=1;
        }
    }
    for(int i=pos;i>=1;i--)
    {
        if(vis[i]) continue;
        if(minn>=i)
        {
            v2.push_back(i);
            vis[i]=1;
            minn-=i;
        }
    }
    if(a>=b)
    {
        printf("%d\n",v1.size());
        for(int i=0;i<v1.size();i++) printf("%d ",v1[i]);
        printf("\n%d\n",v2.size());
        for(int i=0;i<v2.size();i++) printf("%d ",v2[i]);
    }
    else
    {
        printf("%d\n",v2.size());
        for(int i=0;i<v2.size();i++) printf("%d ",v2[i]);
        printf("\n%d\n",v1.size());
        for(int i=0;i<v1.size();i++) printf("%d ",v1[i]);
    }
    return 0;
}


D. Minimum path

题意

给你一个字符矩阵,起点在左上角,每次可以向右或者向下走,可以改变这个字符矩阵中的k个字符,是这个路径构成的字符串字典序最小。

做法

由于可以改变k个字符,那么肯定是找到一条路径,前面至少有k项为a,
后面按照字典序选择路径就可以。
所以我们先用dp[i][j]表示从原点到(i,j)的路径中a最多有多少个。
之后对所有dp[i][j]-(i+j-1)>=k的点中选一个(i+j-1)最大的,
也就是能让前缀全是a的最长前缀,然后把所有满足的丢进vector
用滚动的vector每次选出往后走的字典序最小的,再丢尽vector
对每个点存一下他的上一个点,pre[i][j]
走到最后vector的大小为1,也就是走到终点,
最后通过pre[i][j]逆序输出答案

代码

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair <int, int> pii;
const int maxn = 2005;
int n,k,dp[maxn][maxn];
int vis[maxn][maxn];
pii mp[maxn][maxn];
char pic[maxn][maxn];
vector<pii> ans[2];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",pic[i]+1);
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(pic[i][j]=='a')
            {
                dp[i][j]=max(dp[i-1][j],dp[i][j-1])+1;
            }
            else
            {
                 dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }
    k=min(k,2*n-1);
    int maxx=k;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(dp[i][j]>=(i+j-1)-k) maxx=max(maxx,i+j-1);
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
             if(dp[i][j]>=(i+j-1)-k&&(i+j-1)==maxx)
             {
                 ans[0].push_back(pii(i,j));
             }
        }
    }
    string tmp="";
    for(int i=1;i<=maxx;i++) tmp+='a';
    int left;
    if(tmp=="")
    {
        left=2*n-2;
        ans[0].push_back(pii(1,1));
    }
    else
    {
        left=2*n-1-maxx;
    }
    for(int i=0;i<left;i++)
    {
        int minn=25;
        for(int j=0;j<ans[i%2].size();j++)
        {
            int stx=ans[i%2][j].first;
            int sty=ans[i%2][j].second;
            if(stx<n) minn=min(minn,pic[stx+1][sty]-'a');
            if(sty<n) minn=min(minn,pic[stx][sty+1]-'a');
        }
        ans[(i+1)%2].clear();
        for(int j=0;j<ans[i%2].size();j++)
        {
            int stx=ans[i%2][j].first;
            int sty=ans[i%2][j].second;
            if(stx<n)
            {
                if(pic[stx+1][sty]-'a'==minn&&!vis[stx+1][sty])
                {
                    vis[stx+1][sty]=1;
                    mp[stx+1][sty]=pii(stx,sty);
                    ans[(i+1)%2].push_back(pii(stx+1,sty));
                }
            }
            if(sty<n)
            {
                if(pic[stx][sty+1]-'a'==minn&&!vis[stx][sty+1])
                {
                    vis[stx][sty+1]=1;
                    mp[stx][sty+1]=pii(stx,sty);
                    ans[(i+1)%2].push_back(pii(stx,sty+1));
                }
            }
        }
    }
    string ans="";
    int sx=n,sy=n;
    while(sx+sy-1>maxx)
    {
        ans+=pic[sx][sy];
        pii tmp=mp[sx][sy];
        sx=tmp.first;
        sy=tmp.second;
    }
    reverse(ans.begin(),ans.end());
    tmp+=ans;
    printf("%s\n",tmp.c_str());
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/84508632