Codeforces Round #658 (Div. 2) C2 Prefix Flip (Hard Version)【构造匹配】[规定步数内达成目标的题目]

题目

一种操作,可以选择前缀长度为k,翻转前k的01值然后顺序再倒一下。
要求在2n步内把给定a串变成b串

做法:
a:01101 01001
b:10000 10001
以这个为例,因为要求是2n步内,很容易就想到每个点搞最多两次搞出来,于是就可以2步之内缩小一次问题规模,从n一直缩小到0;

a[1]和b[n]要对上,直接前k翻转.
现在变成谁和谁对上?b[n]和a[n]现在都可以不用管了,于是来到了b[n-1],那b[n-1]和谁对上了,当然还是a[1],a[1]可不就是上一个a[n]吗?可是我们还要用一个值记录全体翻转了几次,(a[1]+i)%2才是真正的值。然后我们发现这个a[1]在原序列中跳跃是这样的
pos=: 1 n 2 n-1 3 …一直到n/2;

于是代码就出来了:
code

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
//
using namespace std;
const int INF = 0x3f3f3f3f;//1.06e9大小
const int mod = 1e9 + 9;
const int mod2 = 998244353;
const int mod3 = 1e9;
const double PI = 3.14159265;
const double eps =1e-8;
typedef unsigned long long ULL;
typedef long long LL;
const int sq5=616991993;
#define ms(x, n) memset(x,n,sizeof(x))
#define debug printf("***debug***\n")
#define pii pair
#define X first
#define Y second
#define pb push_back
//以下define不能在团队赛中使用
#define rep(i,from,to) for(int i=from;i<=to;++i)
#define per(i,from,to) for(int i=from:i>=to;--i)
/*
*/
const int MAXN = 1e5+10;
int a[MAXN];
int b[MAXN];
int ans[2*MAXN];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){scanf(" %c",&a[i]);a[i]-='0';}
        for(int i=1;i<=n;++i){scanf(" %c",&b[i]);b[i]-='0';}
        int cnt=0;//0表示相向匹配,1为同比较
        int pos=1;
        for(int i=1;i<=n;++i)
        {//a的pos和b的n-i+1位
            if(b[n-i+1]==(a[pos]+i-1)%2)ans[cnt++]=1;
            ans[cnt++]=n-i+1;
            if(pos<=n/2)pos=n-pos+1;
            else pos=n-pos+2;
        }
        printf("%d ",cnt);
        for(int i=0;i<cnt;++i)printf("%d ",ans[i]);
        printf("\n");
    }

    return 0;
}


你可能感兴趣的:(Div题解)