本文持续直播,CF比赛出到哪,这里就吐槽到哪,风雨无阻,绝不下播。
说明:cf官网中国大陆不太稳定,所以链接基本上都是国内镜像链接。另外,挂新加坡的VPN比俄罗斯本国的还快。提交账号均为AdaChambers(我的小小号)。
文章目录
- Codeforces Round #658 (Div. 2)C2.Prefix Flip (Hard Version)
- Codeforces Round #657 (Div. 2)D. New Passenger Trams
- Educational Codeforces Round 91D. Berserk And Fireball
- Codeforces Round #655 (Div. 2)D. Omkar and Circle
- Educational Codeforces Round 90 (Rated for Div. 2)C.Pluses and Minuses
- Educational Codeforces Round 90 (Rated for Div. 2)D.Maximum Sum on Even Positions
- Educational Codeforces Round 89C. Palindromic Paths
- Educational Codeforces Round 89D. Two Divisors
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-=