Codeforces Round #658 (Div. 1)

用灰号打的div2但我还是写div1题解吧(因为div2前2题过水)

A

可以发现这样的做法:每次找到最靠后的与b不同从串,然后通过旋转满足条件。但要判断a的第一位与该位是否相同,若相同,则需变换第1位使得其满足翻转后与该位相同,操作数2*n。至于翻转操作,打标记即可

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7;
int n,k,t,a[N],b[N],c[N];
char sa[N],sb[N];
void solve(int l,int r)
{
    if(l==r){if((a[l]^t)!=b[1])c[++k]=1;return;}
    int now=r,m=abs(r-l)+1,dir=l<r?-1:1,tmp=m;
    while(now-dir!=l&&(a[now]^t)==b[tmp])now+=dir,tmp--;
    if(now-dir==l)return;
    if(now==l){c[++k]=1;return;}
    if((a[l]^t)==b[tmp])c[++k]=1,a[l]^=1;
    t^=1,c[++k]=abs(l-now)+1;
    solve(now,l-dir);
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%s%s",&n,sa+1,sb+1);
        k=t=0;
        for(int i=1;i<=n;i++)a[i]=sa[i]-'0',b[i]=sb[i]-'0';
        solve(1,n);
        printf("%d",k);for(int i=1;i<=k;i++)printf(" %d",c[i]);
        puts("");
    }
}
View Code

B

从大到小搜索数,若该数未标记,则该数后面所有未标记的数都与该数在一个集合,并将其标记,记录该集合大小。统计完所有集合大小,再进行背包DP

#include<bits/stdc++.h>
using namespace std;
const int N=4005;
int n,m,a[N],p[N],b[N],w[N];
bool f[N];
int main()
{
    int T;scanf("%d",&T);
    f[0]=1;
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++)scanf("%d",&a[i]),p[a[i]]=i,f[i]=0;
        f[0]=1;
        for(int i=1;i<=2*n;i++)b[i]=1;
        m=0;
        for(int i=2*n;i;i--)
        if(b[p[i]])
        {
            w[++m]=0;
            for(int j=p[i];j<=2*n;j++)if(b[j])b[j]=0,++w[m];
        }
        for(int i=1;i<=m;i++)
        for(int j=n;j>=w[i];j--)
        f[j]|=f[j-w[i]];
        if(f[n])puts("YES");else puts("NO");
    }
}
View Code

div2 rank9 rating+=523(总算找到一点做题感觉)

posted @ 2020-07-22 08:32  hfctf0210  阅读(337)  评论(0编辑  收藏  举报