CF1320D Reachable Strings

发布时间 2023-12-15 16:42:19作者: blueparrot

110和011互相转化,相当于就是0在连续两个1的情况下,移动两个位置

能够发现,0的位置的奇偶不会改变,且很多个0之间的相对位置不会改变

猜想考虑这个答案只跟0的奇偶性有关,下面小证一下:(注意下面所说的“奇偶”指的是两个字符串的分别第一个字母为奇数时的奇偶,不是总字符串的奇偶)

  1. 若0的相对位置奇偶不一样,显然非法

  2. 若0的相对位置奇偶一样,是否合法?假定我们把两个字符串的0都尽可能往左移动,再判断是否相等,这个方法正确性显然。

    现在假设我已经将两个字符串尽可能把0往右移动了,如果是非法情况,也就是说有一个字符串无法移动到下一个和它奇偶性相同且另外一个字符串的存在0的那个位置,那么子串不可能出现连续两个1,必然会有0将他们隔断,然后就不符合上面假设的相对位置奇偶相同了

所以,直接对奇偶比较是正确的,直接奇偶起点分别哈希就行了,实现题解有很多,具体实现注意求一段子串哈希并不能用传统的方式求

#include<bits/stdc++.h>
#define il inline 
#define maxn 200005
using namespace std;
typedef long long ll;
const int base=131;
const ll mod=998244353;
il int read(){
	char c;int x=0,f=0;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))x=(x*10)+(c^48),c=getchar();
	return f?-x:x;
}
int n;
char s[maxn];
ll hs1[maxn],hs2[maxn],bs[maxn],id[maxn];
il int geths(int l,int r,int p){
	if(p)return ((hs1[r]-hs1[l-1]*bs[id[r]-id[l-1]]%mod)%mod+mod)%mod;
	else return ((hs2[r]-hs2[l-1]*bs[id[r]-id[l-1]]%mod)%mod+mod)%mod;
}
int main(){
	n=read();
	scanf("%s",(s+1));
	bs[0]=1;
	for(int i=1;i<=n;i++){
		bs[i]=(bs[i-1]*base)%mod,id[i]=id[i-1];
		if(s[i]=='1')hs1[i]=hs1[i-1],hs2[i]=hs2[i-1];
		else{
			hs1[i]=hs1[i-1]*base+1+(i&1),hs1[i]%=mod;
			hs2[i]=hs2[i-1]*base+1+((i&1)^1),hs2[i]%=mod;
			id[i]++;
		}
	}
	int t=read();
	while(t--){
		int l1=read(),l2=read(),len=read();
		int r1=l1+len-1,r2=l2+len-1;
		geths(l1,r1,l1&1)==geths(l2,r2,l2&1)?puts("Yes"):puts("No");
	}
	return 0;
}
/*
3
010
1
1 3 1
*/