【线段树+HASH】CODEFORCES 580E Kefa and Watch

通道

题意:0-9字符串,区间修改,区间询问是否d周期

思路:直接暴力线段树,然后HASH修改和查询,卡HASH的话就双HASH。

代码:

#include<cstdio>
#include<cstring>

typedef long long ll;

const int N = 100007;
int n, m, k, lens;
char s[N];

#define lch id<<1
#define rch id<<1|1

class HashTree{
public:
    int mod, p;
    ll powp[N], sump[N];
    void getpowp(){
        powp[0] = 1;
        sump[0] = 1;
        for(int i = 1; i < N; i++){
            powp[i] = powp[i-1] * p;
            if(powp[i] >= mod) powp[i] %= mod;
            
            sump[i] = sump[i-1] + powp[i];
            if(sump[i] >= mod) sump[i] %= mod;
        }
    }
    ll v[N << 2];
    int len[N << 2];
    char lazy[N << 2];
    void plant(int id,int l,int r){
        lazy[id] = '\0';
        if(l == r){
            v[id] = s[l];
            len[id] = 1;
            return;
        }
        int mid = (l + r) >> 1;
        plant(lch, l, mid);
        plant(rch, mid + 1, r);
        len[id] = len[lch] + len[rch];
        v[id] = v[lch] * powp[len[rch]] + v[rch];
        if(v[id] >= mod) v[id] %= mod;
    }
    void pushdown(int id){
        if(lazy[id] != '\0'){
            lazy[lch] = lazy[rch] = lazy[id];
            
            v[lch] = lazy[id] * sump[len[lch] - 1];
            if(v[lch] >= mod) v[lch] %= mod;
            
            v[rch] = lazy[id] * sump[len[rch] - 1];
            if(v[rch] >= mod) v[rch] %= mod;
            
            lazy[id] = '\0';
        }
    }
    void update(int id,int ql,int qr,int l,int r,char c){
        if(ql == l && qr == r){
            lazy[id] = c;
            v[id] = c * sump[len[id] - 1];
            if(v[id] >= mod) v[id] %= mod;
            return;
        }
        pushdown(id);
        int mid = (l + r) >> 1;
        if(qr <= mid) update(lch, ql, qr, l, mid, c);
        else if(mid < ql) update(rch, ql, qr, mid + 1, r, c);
        else update(lch, ql, mid, l, mid, c), update(rch, mid + 1, qr, mid + 1, r, c);
        
        v[id] = v[lch] * powp[len[rch]] + v[rch];
        if(v[id] >= mod) v[id] %= mod;
    }
    ll query(int id,int ql,int qr,int l,int r){
        if(ql == l && qr == r){
            return v[id];
        }
        pushdown(id);
        int mid = (l + r) >> 1;
        if(qr <= mid) return query(lch, ql, qr, l, mid);
        else if(mid < ql) return query(rch, ql, qr, mid + 1, r);
        else{
            ll t1 = query(lch, ql, mid, l, mid);
            ll t2 = query(rch, mid + 1, qr, mid + 1, r);
            ll t = t1 * powp[qr - (mid + 1) + 1] + t2;
            if(t >= mod) t %= mod;
            return t;
        }
    }
}tree1, tree2;

bool equal(int l1, int r1, int l2, int r2){
    if(tree1.query(1, l1, r1, 0, lens - 1) != tree1.query(1, l2, r2, 0, lens - 1)) return false;
    if(tree2.query(1, l1, r1, 0, lens - 1) != tree2.query(1, l2, r2, 0, lens - 1)) return false;
    return true;
}

bool judge(int l, int r, int d){
    if(r - l + 1 == d) return true;
    int l2 = l + d, r2 = r;
    int l1 = l, r1 = r - d;
    return equal(l1, r1, l2, r2);
}

int main(){
    tree1.mod = 1e9 + 7, tree1.p = 799817, tree1.getpowp();
    tree2.mod = 1e9 + 9, tree2.p = 451309, tree2.getpowp();
    scanf("%d%d%d",&n,&m,&k);
    scanf("%s",s);
    lens = (int)strlen(s);
    tree1.plant(1, 0, lens - 1), tree2.plant(1, 0, lens - 1);
    for(int i = 1; i <= m + k; i++){
        int ty, l, r;
        scanf("%d%d%d",&ty,&l,&r);
        l--, r--;
        if(ty == 1){
            char c[5];
            scanf("%s",c);
            tree1.update(1, l, r, 0, lens - 1, c[0]);
            tree2.update(1, l, r, 0, lens - 1, c[0]);
        }
        else{
            int d;
            scanf("%d",&d);
            printf("%s\n", judge(l, r, d) ? "YES" : "NO");
        }
    }
    return 0;
}
View Code

 

posted @ 2015-09-23 20:33  mithrilhan  阅读(291)  评论(0编辑  收藏  举报