[codeforces 1382C2] Prefix Flip (Hard Version) 翻转的利器双指针(构造)

别来无恙 提交于 2020-08-06 12:07:18

Codeforces Round #658 (Div. 2)   参与排名人数14674

[codeforces 1382C2]   Prefix Flip (Hard Version)   翻转的利器双指针(构造)

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1382/problem/C2

Problem Lang Verdict Time Memory
C2 - Prefix Flip (Hard Version) GNU C++17 Accepted 62 ms 4600 KB

题目大意:通过操作,将字串a变成字串b.操作规则,必须对字串a从头开始处理,取反,翻转。有操作次数的限制。输出操作次数,及每次操作对应的区间。

基本思路:涉及翻转,需上双指针。需记录取反的次数,需记录翻转的方向。读者若能弄懂下面的样例模拟过程,应该能编写成功。

样例模拟如下:

2
01
10

a b位置1 2
a  元素0 1
b  元素1 0

因a[1]==b[2],需变换a的区间[1,1]
a b位置1 2
a  元素1 1
b  元素1 0

因a[1]!=b[2],需变换a的区间[1,2]
a b位置1 2
a  元素0 0
b  元素1 0

因a[1]!=b[1],需变换a的区间[1,1]
a b位置1 2
a  元素1 0
b  元素1 0

输出:
3 1 2 1



5
01011
11100

a b位置1 2 3 4 5
a  元素0 1 0 1 1
b  元素1 1 1 0 0

因a[1]==b[5],需变换a的区间[1,1]
a b位置1 2 3 4 5
a  元素1 1 0 1 1
b  元素1 1 1 0 0

因a[1]!=b[5],需变换a的区间[1,5].对应原始a的区间[1,5],取反,翻转,用掉原始的a[1],剩下区间[2,5]
a b位置1 2 3 4 5
a  元素0 0 1 0 0
b  元素1 1 1 0 0

因a[1]==b[4],需变换a的区间[1,1]
a b位置1 2 3 4 5
a  元素1 0 1 0 0
b  元素1 1 1 0 0

因a[1]!=b[4],需变换a的区间[1,4].对应原始a的区间[2,5],取反,翻转,用掉原始的a[5],剩下区间[2,4]
a b位置1 2 3 4 5
a  元素1 0 1 0 0
b  元素1 1 1 0 0

因a[1]==b[3],需变换a的区间[1,1]
a b位置1 2 3 4 5
a  元素0 0 1 0 0
b  元素1 1 1 0 0

因a[1]!=b[3],需变换a的区间[1,3].对应原始a的区间[2,4],取反,翻转,用掉原始的a[2],剩下区间[3,4]
a b位置1 2 3 4 5
a  元素0 1 1 0 0
b  元素1 1 1 0 0

因a[1]!=b[2],需变换a的区间[1,2].对应原始a的区间[3,4],取反,翻转,用掉原始的a[4],剩下区间[3,3]
a b位置1 2 3 4 5
a  元素0 1 1 0 0
b  元素1 1 1 0 0

因a[1]!=b[1],需变换a的区间[1,1].对应原始a的区间[3,3],取反,翻转,用掉原始的a[3],没有剩下区间
a b位置1 2 3 4 5
a  元素1 1 1 0 0
b  元素1 1 1 0 0

输出:
8 1 5 1 4 1 3 2 1

AC代码如下:

#include <stdio.h>
#include <string.h>
#define maxn 100010
char a[maxn],b[maxn];
int c[maxn<<1],cn;
int main(){
	int t,n,i,l,r,delta,now,change,tmp;//change记录翻转次数
	char d;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		scanf("%s",a+1);
		scanf("%s",b+1);
		l=1,r=n,delta=1,now=n,change=0,cn=0;//delta记录序列的出来方向
		while(1){
			if(change%2==0)d=a[l];//d对应比较的第一个字母
			else d=!(a[l]-'0')+'0';
			if(now==1){//特判,最后只剩一个字母
				if(d!=b[now])cn++,c[cn]=1;
				break;
			}
			if(d!=b[now])cn++,c[cn]=now,now--,tmp=l,l=r,r=tmp+delta,change++,delta*=-1;//d(变换后a中的首字母),now表示处理到的b的字母所处的位置。
			else cn++,c[cn]=1,a[l]=!(a[l]-'0')+'0';//d==b[now];只处理区间[1,1]
		}
		printf("%d",cn);
		for(i=1;i<=cn;i++)printf(" %d",c[i]);
		printf("\n");
	}
	return 0;
}

类似题目:

AtCoder Beginner Contest 158 D String Formation 首尾顺序可变的字符串

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!