C1. Prefix Flip(easy到hard巧妙地构造)

e a s y > h a r d 其实本来想讲从easy->hard的

但是自己的算法可以过两个版本?那就只讲这种方法好了

, , 构造题,每次可以选前缀位运算取反,然后翻转这个前缀

相信棘手的就是这个翻转前缀,使得我们的操作变得复杂,不可控

, 2 n 但是这是一道构造题,只需要在2n的步骤内完成即可

, , ? 那设想一下,如果前缀都是相同,翻转不就不需要考虑了吗?

\color{Red}具体实现分为两个步骤

. a 00000...00000 Ⅰ.把a串变成00000...00000的形式

. 00000..00000 b Ⅱ.把00000..00000变成b串的形式

a 01011 ( 1 ) , 00000 ? 比如当a串等于01011时(下标从1起),如何变成00000?

0 , 一、因为第一位是0,不用管

1 , [ 1 , 1 ] , 11011 二、第二位是1,那么先对[1,1]操作,于是现在变成11011

[ 1 , 2 ] , 00011 然后对[1,2]操作,于是现在变成00011

0 , 三、第三位是0,不用管

1 , [ 1 , 3 ] , 11111 四、第四位是1,那先对[1,3]操作,于是现在变成11111

[ 1 , 4 ] , 00001 然后对[1,4]操作,于是现在变成00001

. . . . . . . . . . . . . . ..............

, a x 1 , [ 1 , x 1 ] 使 1 总之,一旦a串的x位置是1,就操作[1,x-1]使得这个区间变成1

[ 1 , x ] 使 0 再操作[1,x]区间使得这个区间都变成0

00000 b 11001 ? \color{Red}如何从00000变成b串11001?

, 这个就不难想了,和上面差不多的思想

, b x 1 从高位往低位看,如果b串的x位置是1

[ 1 , x ] 使 a [ 1 , x ] 1 那么操作[1,x]使得a串[1,x]都是1

[ 1 , x 1 ] , 使 a [ 1 , x 1 ] 0 再操作[1,x-1],使得a串的[1,x-1]还原为0

. . . . . . . 一直重复下去.......

那么有代码

if( a[1]=='1' )	vec.pb(1);
for(int i=2;i<=n;i++)
{
	if( a[i]=='0' )	continue;
	else vec.pb(i-1),vec.pb(i);//操作[1,i-1]变成1,再操作[1,i]都变0
}
for(int i=n;i>=2;i--)
{
	if(b[i]=='0')	continue;
	else
	{
		vec.pb(i);
		vec.pb(i-1);
	}
}
if( b[1]=='1' )	vec.pb(1);

但是就可以发现这样写做多的操作次数可能超过了2n次

, 观察一下上面的操作过程,其实我们可以对操作去重

[ 1 , i ] , , 因为如果进行了偶数次操作区间[1,i],等于没操作,直接去掉

[ 1 , i ] , 如果进行了奇数次操作区间[1,i],只保留一次

a > 00000 , , n 所以在a->00000时,每个位置最多操作一次,也就是n次

00000 > b , , n , 2 n 在00000->b时,每个位置最多操作一次,也就是n次,加起来2n次

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
int t,n;
char a[200009],b[200009];
typedef pair<int,int>p;
vector<int>vec,s;
int main()
{
	cin >> t;
	while(t--)
	{
		vec.clear();s.clear();
		cin >> n >> (a+1) >> (b+1);
		int flag=0;
		for(int i=1;i<=n;i++)
			if(a[i]!=b[i])	flag=1;
		if( flag==0 )
		{
			cout<<0<<endl;
			continue;
		}
		if( a[1]=='1' )	vec.pb(1);
		for(int i=2;i<=n;i++)
		{
			if( a[i]=='0' )	continue;
			else vec.pb(i-1),vec.pb(i);
		}
		for(int i=n;i>=2;i--)
		{
			if(b[i]=='0')	continue;
			else
			{
				vec.pb(i);
				vec.pb(i-1);
			}
		}
		if( b[1]=='1' )	vec.pb(1);
		int last=vec[0],temp=1;
		for(int i=1;i<vec.size();i++)
		{
			if( vec[i]!=last )
			{
				if( temp%2==1 )	s.pb(last);
				temp=1,last=vec[i];
			}
			else	temp++;
		}
		if( temp%2==1 )	s.pb(last);
		cout<<s.size()<<" ";
		for(int i=0;i<s.size();i++)	cout<<s[i]<<" ";
		cout<<endl;
	}
}

emmm讲完啦,希望对你有帮助,一起进步呀!

猜你喜欢

转载自blog.csdn.net/jziwjxjd/article/details/107503946