专栏文章

题解:AT_abc418_d [ABC418D] XNOR Operation

AT_abc418_d题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mio9mt0x
此快照首次捕获于
2025/12/02 15:37
3 个月前
此快照最后确认于
2025/12/02 15:37
3 个月前
查看原文

AT_abc418_d [ABC418D] XNOR Operation题解

简略题目描述

有一个只包含0,10,1的字符串,要求出可以通过(类似异或)的方式能令序列变为11的子串个数。

数据范围

  • 1N2×1051 \leq N \leq 2 \times 10^5
  • NN 是整数。
  • TT 是长度为 NN 的、仅由 01 组成的字符串。
通过观察可知,判断一个子串为美丽字符串和 11 的数量是没有关系的。 因为所有的 11 都可以通过操作变成 1111 ,而发现如果 00 的数量为偶数的话,可以通过一定数量的操作使得序列变成只有 11 的序列,但是如果 00 的数量为奇数的话,无论怎么合并,会剩下一个单独的 00 无法合并
于是问题转换为了求连续区间内 00 的个数为偶数的数量。而我们可以用前缀和来解决一个区间内的 00 的个数,再用区间长度减去当以 ii 为左端点,且区间 00 的数量为奇数的区间个数即可。 于是就可以省去枚举 rr 的循环了。
时间复杂度:O(n)O(n)
空间复杂度:O(n)O(n)
代码细节详见注释。
code(码风丑陋,请见谅(无坑,放心食用)) :
CPP
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int nn=2e5+5;
int n,s[nn],ji[nn][2],la[nn],v,e,ans;
string t;
//s[i]表示1-i的0的个数
//la[i]表示离i最近的0的位置(包括i)
//ji[i][0]=1表示当前有偶数个0
//ji[i][1]=1表示当前有奇数个0
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n>>t;
	t=" "+t;
	for(int i=1;i<=n;i++){
		s[i]=s[i-1];
		if(t[i]=='0'){
			v++;
			e^=1;
			s[i]++,la[i]=i;
		}else{
			la[i]=la[i-1];
		}
		ji[i][e]=1;//差分
	}
	for(int i=1;i<=n;i++)ji[i][0]+=ji[i-1][0],ji[i][1]+=ji[i-1][1];//前缀和
	int v=s[n];
	for(int i=1;i<=n;i++){
		if(s[i-1]%2==1){//当前出现了奇数个0
			ans+=(n-i+1);
			ans-=(ji[n][0]-ji[i-1][0]);//前缀和
		}else {//当前出现了偶数个0
			ans+=(n-i+1);
			ans-=(ji[n][1]-ji[i-1][1]);//前缀和
		}
	}
	cout<<ans;
	return 0;
}
蒟蒻赛时调了30min,导致ee题差 10min10 min写出(TAT)

评论

0 条评论,欢迎与作者交流。

正在加载评论...