CF1237H. Balanced Reversals

题目大意

给出长为n(n是偶数)的01串S,每次可以把一个长度为偶数的前缀翻转,构造至多n+1次操作把串S变成串T或输出无解

n<=4000

题解

讲杂题时并没有给出操作次数限制,所以以为可以乱做,想每次翻到末尾,这样是3/2n次

首先把两个合成一组,如果01+10、00、11的个数不相等就无解

然后考虑从头开始构造,维护一段前缀[1,i]使得rev(S[1,i])=T[1,i],接着每次用两次操作即可把后面的某个接到前面来,最后再把[1,n-2]翻转即可得到T,过程中由于翻了两次所以01和10不会变

问题是使一开始的01和10个数相等,找到ST中0110差绝对值较大者,将其的一个前缀翻转

因为差的绝对值越大说明01的个数越靠近0或n/2,反过来的过程中一定会与另一个相遇

总操作次数为2(n/2-1)+1+1=n

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define abs(x) ((x)>0?(x):-(x))
#define ll long long
//#define file
using namespace std;

int a[4001],b[4001],sum[4],Sum[4],Q,n,N,i,j,k,l,Ls,tot;
int ans[4002];
char S[4001],T[4001];

void swap(int &x,int &y) {int z=x;x=y;y=z;}
int turn(char a,char b) {if (a==b) {return (a=='0')?2:3;} if (a=='0') return 0;return 1;}
void rev(int *a,int t)
{
	int i;
	fd(i,t/2,1) swap(a[i],a[t-i+1]);
	fo(i,1,t) if (a[i]<=1) a[i]^=1;
}

int main()
{
	#ifdef file
	freopen("CF1237H.in","r",stdin);
	#endif
	
	scanf("%d",&Q);
	for (;Q;--Q)
	{
		scanf("%s",S+1),scanf("%s",T+1);
		n=strlen(S+1),tot=0,N=n/2;
		memset(sum,0,sizeof(sum));
		memset(Sum,0,sizeof(Sum));
		fo(i,1,N) a[i]=turn(S[i*2-1],S[i*2]),++sum[a[i]];
		fo(i,1,N) b[i]=turn(T[i*2-1],T[i*2]),++Sum[b[i]];
		if (sum[0]+sum[1]!=sum[0]+sum[1] || sum[2]!=Sum[2] || sum[3]!=Sum[3]) {printf("-1\n");continue;}
		
		Ls=-1,tot=0;
		if (sum[0]!=Sum[0])
		{
			if (abs(sum[0]-sum[1])>abs(Sum[0]-Sum[1]))
			{
				fo(i,1,N)
				if (a[i]<=1)
				{
					--sum[a[i]],++sum[a[i]^1];
					if (sum[0]==Sum[0]) {rev(a,i);ans[++tot]=i;break;}
				}
			}
			else
			{
				fo(i,1,N)
				if (b[i]<=1)
				{
					--Sum[b[i]],++Sum[b[i]^1];
					if (sum[0]==Sum[0]) {rev(b,i);Ls=i;break;}
				}
			}
		}
		
		fo(i,1,N-1)
		{
			fo(j,i,N)
			if (a[j]==b[i])
			{
				if (j>1) rev(a,j-1),ans[++tot]=j-1;
				rev(a,j),ans[++tot]=j;
				break;
			}
		}
		if (N>1) rev(a,N-1),ans[++tot]=N-1;
		
		if (Ls>-1) ans[++tot]=Ls;
		printf("%d\n",tot);
		fo(i,1,tot) printf("%d ",ans[i]*2);
		printf("\n");
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
posted @ 2020-11-23 20:20  gmh77  阅读(290)  评论(1编辑  收藏  举报