DIV2机智题集锦

本文持续直播CF比赛,深入解析比赛题目,分享解题思路与技巧,包括PrefixFlip、NewPassengerTrams、BerserkAndFireball等热门题目。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文持续直播,CF比赛出到哪,这里就吐槽到哪,风雨无阻,绝不下播。
说明:cf官网中国大陆不太稳定,所以链接基本上都是国内镜像链接。另外,挂新加坡的VPN比俄罗斯本国的还快。提交账号均为AdaChambers(我的小小号)。

Codeforces Round #658 (Div. 2)C2.Prefix Flip (Hard Version)

题目链接

https://codeforc.es/problemset/problem/1381/A2

题意

就是想按一定的规则把01序列a变为序列b。每次选一个前缀,按位取反后翻转。完了操作次数不超过2n次。输出方案。

题解

首先发现一个有趣的性质:用i-j-i这样的三连操作,就能把i位之前的j位取反后翻转。并且保持其他不变。用这个就能线性求出easy version的结果。因为每个不相同的位花i-1-i三次操作就相同了,这样3n次就行。但是如何2n呢?这个我是强行乱搞的。我看看三个连着都不相等的,并且按照a中三位的8中可能来进行1或2次i-x-i的操作,最多6次操作就能把三位都变相同。这样三个的最多6次,平均一个2次,没有三连不同的地方就按easy versioin一位一位弄,没有三连不同的地方,最坏的是两个不同连着一个相同,所以至多有2/3n个数用单个取反的,这样不管怎样平均一个数最多2次,就乱搞过了。注意开始第1个数特判一下。

吐槽

这场太惨了。我这题早就有思路了。但是比赛摸鱼,最后急急匆匆居然没交上,排名4000+。瞬间rt暴跌,到了1600+,完全回到解放前了。

AC代码

#include<cstdio>
#include<cstring>
using namespace std;
const int NN=1e5+10;
char a[NN],b[NN];
int main(){
	int t;scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		scanf("%s",a+1);
		scanf("%s",b+1);
		for(int i=1;i<=n;i++){
			a[i]-='0';
			b[i]-='0';
		}
		int ans=0;
		for(int i=n;i>=1;){
				if(i>=3&&a[i]!=b[i]&&a[i-1]!=b[i-1]&&a[i-2]!=b[i-2]){
					if(a[i-2]==0&&a[i-1]==0&&a[i]==0){
						ans+=3;
					}
					else if(a[i-2]==0&&a[i-1]==0&&a[i]==1){
						ans+=6;
					}
					else if(a[i-2]==0&&a[i-1]==1&&a[i]==0){
						ans+=3;
					}
					else if(a[i-2]==0&&a[i-1]==1&&a[i]==1){
						ans+=6;
					}
					else if(a[i-2]==1&&a[i-1]==0&&a[i]==0){
						ans+=6;
					}
					else if(a[i-2]==1&&a[i-1]==0&&a[i]==1){
						ans+=3;
					}
					else if(a[i-2]==1&&a[i-1]==1&&a[i]==0){
						ans+=6;
					}
					else if(a[i-2]==1&&a[i-1]==1&&a[i]==1){
						ans+=3;
					}
					i-=3;
				}
				else if(i==1&&a[i]!=b[i]){
					ans+=1;
					i--;
				}
				else if(a[i]!=b[i]){
					ans+=3;
					i--;
				}
				else i--;
		}
		printf("%d ",ans);
		for(int i=n;i>=1;){
				if(i>=3&&a[i]!=b[i]&&a[i-1]!=b[i-1]&&a[i-2]!=b[i-2]){
					if(a[i-2]==0&&a[i-1]==0&&a[i]==0){
						printf("%d %d %d ",i,3,i);
					}
					else if(a[i-2]==0&&a[i-1]==0&&a[i]==1){
						printf("%d %d %d ",i-1,2,i-1);
						printf("%d %d %d ",i,1,i);
					}
					else if(a[i-2]==0&&a[i-1]==1&&a[i]==0){
						printf("%d %d %d ",i,3,i);
					}
					else if(a[i-2]==0&&a[i-1]==1&&a[i]==1){
						printf("%d %d %d ",i-2,1,i-2);
						printf("%d %d %d ",i,2,i);
					}
					else if(a[i-2]==1&&a[i-1]==0&&a[i]==0){
						printf("%d %d %d ",i-2,1,i-2);
						printf("%d %d %d ",i,2,i);
					}
					else if(a[i-2]==1&&a[i-1]==0&&a[i]==1){
						printf("%d %d %d ",i,3,i);
					}
					else if(a[i-2]==1&&a[i-1]==1&&a[i]==0){
						printf("%d %d %d ",i-1,2,i-1);
						printf("%d %d %d ",i,1,i);
					}
					else if(a[i-2]==1&&a[i-1]==1&&a[i]==1){
						printf("%d %d %d ",i,3,i);
					}
					i-=