字符串hash+思维——cf1320D

/*
奇数位上的0只能移动到奇数位,偶数同理 
t1,t2可互相转化的一些推论
1.t1,t2里0的个数相等 
2.t1里所有0的相对位置不会变化,所以t1,t2里所有对应的0奇偶性必须相等

把原串所有0按照位置的奇偶性进行hash,然后考虑如何快速hash t1,t2里的0序列 
找到t1,t2里第1个0,求出其奇偶性,后面的那些0可以直接通过字符串hash得到
然后再拼凑一下即可 
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define mod 19260817
#define P 13331
#define N 200005

char t[N];
int n,q;
ll has[N],len[N];
vector<int>v;

ll F[N];
void prework(){
    F[0]=1;
    for(int i=1;i<=n;i++)F[i]=F[i-1]*P%mod;
    for(int i=1;i<v.size();i++){
        if(len[i]%2==0)has[i]=has[i-1]*P%mod;
        else has[i]=(has[i-1]*P%mod+1)%mod;
    }
}

ll gethash(ll l,ll r){
    return (has[r]-has[l-1]*F[r-l+1]%mod+2*mod)%mod;
}

int main(){
    cin>>n>>(t+1)>>q;
    
    v.push_back(0);
    for(int i=1;i<=n;i++)
        if(t[i]=='0')v.push_back(i);
    if(v.size())len[1]=v[1];
    for(int i=2;i<v.size();i++) 
        len[i]=v[i]-v[i-1];    
    v.push_back(n+1);
    
    prework();
    sort(v.begin(),v.end());
    //cout<<v[0]<<v[1]<<'\n';
    while(q--){
        int l,r,len;scanf("%d%d%d",&l,&r,&len);
        int posl1=lower_bound(v.begin(),v.end(),l)-v.begin();
        int posr1=upper_bound(v.begin(),v.end(),l+len-1)-v.begin()-1;
        int posl2=lower_bound(v.begin(),v.end(),r)-v.begin();
        int posr2=upper_bound(v.begin(),v.end(),r+len-1)-v.begin()-1;
        
        if(posr1-posl1!=posr2-posl2){puts("No");continue;} //判0个数 
        
        if(posr1<posl1 && posr2<posl2){puts("Yes");continue;}//没有0; 
        
        if((v[posl1]-l)%2 != (v[posl2]-r)%2){puts("No");continue;}//判第一个0 
        
        if(posl1==posr1){puts("Yes");continue;}//只有一个0 
        
        ll has1=gethash(posl1+1,posr1),has2=gethash(posl2+1,posr2);
        if(has1==has2){puts("Yes");continue;}
        else puts("No");
    }
} 

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12482388.html