zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    程序猿之没事瞎吐槽
    iOS 打印日志的保存 (一)
    Xcode4.5 本地化,多语言设置
    css3渐变画斜线 demo
    关于JavaScript的一些记录
    Windows 10 自带输入法(微软拼音)繁体简体切换快捷键
    ng-class用法小记
    基于vue监听滚动事件,实现锚点链接平滑滚动
    总结继承的几种方式
    浅谈jQuery的内部框架结构,操作
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4836716.html
Copyright © 2011-2022 走看看