1. 程式人生 > 實用技巧 >CF1237H. Balanced Reversals

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;
}