CF #321 (Div. 2) E
用线段树维护哈希,类似于进位制的一个哈希 a[i]*p^i+a[i-1]*p^i-1...
然后,线段树存在某区间的哈希的值,对于更新,则只需提前计算出整段的哈希值即可。
判断是否相等,由于相隔为d,只需计算(l+d,r),(l,r-d)两段哈希的值是否相等即可。为了防止一次哈希可能使不符合条件的值哈希值相等,所以进行了两次哈希。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define LL long long using namespace std; const int MAX=100010; const LL m1=1000000007; const LL m2=1000000009; const int g1=47; const int g2=67; char str[MAX]; struct HASH{ LL seg[MAX<<2]; int lazy[MAX<<2]; LL bits[10][MAX]; LL mod,gt; LL ebit[MAX]; void init(LL m,LL g){ mod=m; gt=g; for(int i=0;i<MAX;i++){ if(i==0) ebit[i]=1; else { ebit[i]=(ebit[i-1]*gt)%mod; } } for(int i=0;i<=9;i++){ bits[i][0]=0; for(int j=1;j<MAX;j++){ bits[i][j]=(bits[i][j-1]*gt%mod+i)%mod; } } } void push_up(int rt,int l,int r){ seg[rt]=(seg[rt<<1|1]+seg[rt<<1]*ebit[r-(l+r)/2])%mod; } void push_down(int rt,int l,int r){ if(lazy[rt]!=-1){ int m=(l+r)>>1; lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; seg[rt<<1]=bits[lazy[rt]][m-l+1]; seg[rt<<1|1]=bits[lazy[rt]][r-m]; lazy[rt]=-1; } } void build(int rt,int l,int r){ if(l==r){ seg[rt]=(str[l]-'0')%mod; lazy[rt]=-1; return ; } int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r); push_up(rt,l,r); lazy[rt]=-1; } void update(int rt,int l,int r,int L,int R,int d){ if(l<=L&&R<=r){ lazy[rt]=d; seg[rt]=bits[d][R-L+1]; return ; } int m=(L+R)>>1; push_down(rt,L,R); if(m>=l) update(rt<<1,l,r,L,m,d); if(m+1<=r) update(rt<<1|1,l,r,m+1,R,d); push_up(rt,L,R); } void query(int rt ,int l,int r,int L,int R,LL &res){ if(l<=L&&R<=r){ res=(res*ebit[R-L+1]+seg[rt])%mod; return ; } push_down(rt,L,R); int m=(L+R)>>1; if(m>=l) query(rt<<1,l,r,L,m,res); if(m+1<=r) query(rt<<1|1,l,r,m+1,R,res); } bool check(int l,int r,int d,int n){ if(r-l+1==d) return true; LL lrt=0; query(1,l,r-d,1,n,lrt); LL rrt=0; query(1,l+d,r,1,n,rrt); if(lrt==rrt) return true; return false; } }a,b; int main(){ // cout<<"OK"<<endl; int n,m,k,op,l,r,d; // cout<<"OK"<<endl; // HASH a,b; /// cout<<"OK"<<endl; while(scanf("%d%d%d",&n,&m,&k)!=EOF){ scanf("%s",str+1); a.init(m1,g1); b.init(m2,g2); a.build(1,1,n); b.build(1,1,n); /// cout<<"YES"<<endl; m+=k; while(m--){ scanf("%d%d%d%d",&op,&l,&r,&d); if(op==1){ a.update(1,l,r,1,n,d); b.update(1,l,r,1,n,d); } else{ if(a.check(l,r,d,n)&&b.check(l,r,d,n)){ puts("YES"); } else puts("NO") ; } } } return 0; }