Codeforces Round #321 (Div. 2)-E(线段树+hash

题目:给出一个序列,有两种询问,一种是把某个区间的数全部变为一个数,一种是查询一个区间是否为以d为周期.

思路:线段树维护区间的hash值,然后对于一个区间[l,r]如果[l,r-d]和[l+d,r]相等那么这个区间的周期就是d.

注意cf上的自然溢出hash几乎必然被hack....hack方法见此文:http://codeforces.com/blog/entry/4898

 

/*
* @author:  Cwind
*/
#include <bits/stdc++.h>
#define pb push_back
#define PB pop_back
#define bk back()
#define se second
#define fs first
#define IINF (1<<29)
#define sq(x) (x)*(x)
#define eps 0.000000001
#define clr(x) memset((x),0,sizeof (x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll> P;
const int maxn=1e5+399;
ull H=2347;
ull H2=1007;
const ull mod=1e9+7;
ull hashsum[maxn];
ull hashpow[maxn];
int a[maxn];
int n,m,k;
const int maxp=1e6;
struct Node{
    int l,r;
    ull hash;
    int val,s;
    Node *ch[2];
    bool lazy;
    void pushdown(){
        if(r-l<=1) return;
        if(lazy){
            lazy=0;
            ch[0]->lazy=ch[1]->lazy=1;
            ch[0]->val=ch[1]->val=val;
            ch[0]->hash=val*hashsum[ch[0]->s-1]%mod;
            ch[1]->hash=val*hashsum[ch[1]->s-1]%mod;
        }
    }
}pool[maxp];
int ph=0;
Node *newNode(){
    Node *n=&pool[ph++];
    n->lazy=0;
    return n;
}
void build(Node *n,int l,int r){
    n->l=l,n->r=r;
    if(r-l<=1){
        n->hash=a[l];
        n->s=1;
        return;
    }
    n->ch[0]=newNode();
    n->ch[1]=newNode();
    Node *chl=n->ch[0],*chr=n->ch[1];
    build(chl,l,(l+r)/2);
    build(chr,(l+r)/2,r);
    n->s=chr->s+chl->s;
    n->hash=(chl->hash+chr->hash*hashpow[chl->s]%mod)%mod;
}
void update(Node *n,int a,int b,int v){
    n->pushdown();
    int l=n->l,r=n->r;
    if(l>=b||a>=r) return;
    if(a<=l&&b>=r){
        n->lazy=1;
        n->val=v;
        n->hash=v*hashsum[n->s-1]%mod;
        return;
    }
    Node *chl=n->ch[0],*chr=n->ch[1];
    update(chl,a,b,v);
    update(chr,a,b,v);
    n->hash=(chl->hash+chr->hash*hashpow[chl->s]%mod)%mod;
}
ull getHash(Node *n,int a,int b){
    n->pushdown();
    int l=n->l,r=n->r;
    if(l>=b||a>=r) return 0;
    if(l>=a&&r<=b) return n->hash;
    int ll=max(a,l),rr=min(b,r);
    int mid=n->ch[1]->l;
    if(mid>ll){
        return (getHash(n->ch[0],a,b)+getHash(n->ch[1],a,b)*hashpow[mid-ll])%mod;
    }else 
        return getHash(n->ch[1],a,b)%mod;
}
void init(){
    hashsum[0]=1;
    hashpow[0]=1;
    for(int i=1;i<maxn;i++){
        hashsum[i]=(hashsum[i-1]*H+1)%mod;
        hashpow[i]=(hashpow[i-1]*H)%mod;
    }
}
Node *root;
char r[maxn];
int main(){
    ///freopen("/home/files/CppFiles/in","r",stdin);
    //freopen("defense.in","r",stdin);
    //freopen("defense.out","w",stdout);
    init();
    root=newNode();
    cin>>n>>m>>k;
    scanf("%s",r);
    for(int i=1;i<=n;i++){
        a[i]=r[i-1]-'0';
    }
    build(root,1,n+1);
    for(int ttt=0;ttt<m+k;ttt++){
        int o,x,y,z;
        scanf("%d%d%d%d",&o,&x,&y,&z);
        if(o==1){
            update(root,x,y+1,z);
        }else{
            ull hash1=getHash(root,x,y-z+1);
            ull hash2=getHash(root,x+z,y+1);
            if(hash1==hash2){
                puts("YES");
            }else{
                puts("NO");
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2015-09-23 21:09  PlusSeven  阅读(153)  评论(0编辑  收藏  举报