题意:
给你一个01串,你只有两种操作:将某个位置的011变成110或者将某个位置的110变成011.
每次问你两个区间的子串能否相互转换。
题解:
这就是说0能够通过偶数个1转移到另一个位置,也就是两个0如果中间有奇数个1,那么就是说这是两个区间的0.
h[1][i].first=(h[1][i-1].first*23ll+(i&1)+1)%mod;
那么这样子哈希也就是区分了奇偶的位置,也就是说这是奇偶性的哈希而不是通常那样的按位置哈希。(这么优秀的算法一看就不是我自己想的)
为什么有两个哈希数组是因为,要看第一个0前面有多少个1.
但是不知道为什么自动取模一直过不了,我加个取模就过了,可能都不需要双哈希。
#include<bits/stdc++.h>
using namespace std;
#define ull long long
#define pa pair<ull,ull>
const int N=3e5+5;
const ull mod=1e9+7;
pa h[2][N],p[N];
int cnt[N];
char s[N];
pa get_h(int l,int r){
ull h1=(h[l&1][r].first-h[l&1][l-1].first*p[cnt[r]-cnt[l-1]].first%mod+mod)%mod;
ull h2=(h[l&1][r].second-h[l&1][l-1].second*p[cnt[r]-cnt[l-1]].second%mod+mod)%mod;
return {h1,h2};
}
int main()
{
int n;
scanf("%d%s",&n,s+1);
p[0]={1,1};
for(int i=1;i<=n;i++){
p[i].first=p[i-1].first*23ll%mod;
p[i].second=p[i-1].second*131ll%mod;
cnt[i]=cnt[i-1]+(s[i]=='0');
if(s[i]=='0'){
h[0][i].first=(h[0][i-1].first*23ll+((i&1)^1)+1)%mod;
h[0][i].second=(h[0][i-1].second*131ll+((i&1)^1)+1)%mod;
h[1][i].first=(h[1][i-1].first*23ll+(i&1)+1)%mod;
h[1][i].second=(h[1][i-1].second*131ll+(i&1)+1)%mod;
}
else
h[0][i]=h[0][i-1],h[1][i]=h[1][i-1];
}
int q;
scanf("%d",&q);
while(q--){
int p1,p2,l;
scanf("%d%d%d",&p1,&p2,&l);
pa h1=get_h(p1,p1+l-1),h2=get_h(p2,p2+l-1);
if(h1.first==h2.first&&h1.second==h2.second)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}