Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round F. Reachable Strings)
题解:
这个题目不太会写,是一个漂亮的小姐姐教我的~~~
如果两个字符串可以变成一样的,那么显然s可以变成t,s可以变成什么样,那么t肯定也可以变成什么样。
对于操作011变成110,这个是把0往后或者往前面挪两位,0所在位置的奇偶性不变,但是碰到0了就不能挪了,所以对于s和t要判断是否相等,我只要判断这两个串0所在的位置的奇偶性和顺序是否相同,如果都相同,那么就可以变成一样的。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
const int mod1 = 1e9+7;
const int mod2 = 998244353;
ll f1[maxn],f2[maxn];
ll v[maxn],p[maxn];
char s[maxn];
void init(int n){
p[0]=1;
for(int i=1;i<=n;i++) {
p[i]=p[i-1]*3%mod1;
// printf("p[%d]=%lld
",i,p[i]);
}
}
int main(){
int n,now=0;
scanf("%d",&n);
init(n);
scanf("%s",s+1);
for(int i=1;i<=n;i++){
if(s[i]=='0') v[++now]=i;
}
for(int i=1;i<=now;i++) {
int id = v[i];
if (id & 1) {
f1[i] = (f1[i - 1] + 2 * p[i - 1]) % mod1;
f2[i] = (f2[i - 1] + p[i - 1]) % mod1;
} else {
f1[i] = (f1[i - 1] + p[i - 1]) % mod1;
f2[i] = (f2[i - 1] + 2 * p[i - 1]) % mod1;
}
// printf("f1[%d]=%lld f2[%d]=%lld
",i,f1[i],i,f2[i]);
}
int m;
scanf("%d",&m);
while(m--){
int x,y,len;
scanf("%d%d%d",&x,&y,&len);
if(x>y) swap(x,y);
int l1 = lower_bound(v+1,v+1+now,x)-v - 1;
int r1 = upper_bound(v+1,v+1+now,x+len-1)-v - 1;
int l2 = lower_bound(v+1,v+1+now,y)-v - 1;
int r2 = upper_bound(v+1,v+1+now,y+len-1)-v - 1;
if(l1>=r1&&l2>=r2) printf("YES
");
else if(l1>=r1||l2>=r2) printf("NO
");
else{
// printf("l1=%d r1=%d l2=%d r2=%d
",l1,r1,l2,r2);
ll res1 = 0,res2 = 0;
if(x&1) {
// printf("yyy
");
res1 = (f1[r1]-f1[l1]+mod1)%mod1;
}
else res1 = (f2[r1]-f2[l1]+mod1)%mod1;
if(y&1) {
// printf("sss
");
res2 = (f1[r2]-f1[l2]+mod1)%mod1;
}
else res2 = (f2[r2]-f2[l2]+mod1)%mod1;
// printf("res1=%lld res2=%lld
",res1,res2);
res1 = res1*p[l2-l1]%mod1;
if(res1==res2) printf("YES
");
else printf("NO
");
}
}
}
/*
10
0100001001
10
9 8 1
*/