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;
}

 

posted @ 2015-09-24 22:00  chenjunjie1994  阅读(143)  评论(0编辑  收藏  举报