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

来源:互联网 发布:动态特效的软件 编辑:程序博客网 时间:2024/05/21 16:23

题意:

题意大概是给你一串长度为n的数字串,两个操作,1 l r c 将 下标为l 到 r 的数字全部改为 c
2 l r c 询问 下标为l 到 r 的数字 循环节是否为 c
n 的范围是10W, 第二个c的范围是10

思路:

做法就是字符串hash啦,因为字符串hash类似于前缀和的处理,也就是说:比如区间v1[Lmid和区间v2mid+1R合并成LR。那么区间L,R的值就是v2+v1Plengthv2,这样的话,是不是就可以去用线段树查询或者是区间更新维护了呢?

两份代码:

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <iostream>#include <cmath>#include <map>#include <vector>#include <set>#include <string>#define PB push_back#define FT first#define SD second#define MP make_pair#define INF 0x3f3f3f3fusing namespace std;typedef long long LL;typedef unsigned long long ULL;const int N=5+1e5;const LL MOD=7+1e9;const LL seed=49681;;LL pw[N];int n,lazy[4*N];LL ch[11][N],H[4*N];void init(){    pw[0]=1LL;    for(int i=1;i<=n;i++) {        pw[i] = pw[i-1]*seed % MOD;    }    for(int i=1;i<=10;i++){        ch[i][0]=0;        for(int j=1;j<=n;j++) {            ch[i][j]=(ch[i][j-1]*seed%MOD + i) %MOD ;        }    }}void pushdown(int rt,int L,int R){    int T=lazy[rt],mid=(L+R)>>1;    lazy[rt]=0;    lazy[2*rt]=lazy[2*rt+1]=T;    H[2*rt]=ch[T][mid-L+1],H[2*rt+1]=ch[T][R-mid];}void update(int rt,int L,int R,int l,int r,int v){    if(l<=L && R<=r) {        H[rt] = ch[v][r-l+1];        //cout<<v<<" "<<l<<" "<<r<<" "<<H[rt]<<endl;        lazy[rt]=v;        return ;    }    else {        int mid=(L+R)>>1;        if(lazy[rt]) pushdown(rt,L,R);        if(r<=mid) update(rt*2,L,mid,l,r,v);        else if(l>mid) update(2*rt+1,mid+1,R,l,r,v);        else {            update(2*rt,L,mid,l,mid,v);            update(2*rt+1,mid+1,R,mid+1,r,v);        }        H[rt] = (H[rt*2]*pw[R-mid]%MOD+H[2*rt+1])%MOD;    }}LL query(int rt,int L,int R,int l,int r){    //cout<<L<<" "<<R<<" "<<l<<" "<<r<<endl;    if(l<=L && R<=r) {        //cout<<"NOW: "<<l<<" "<<r<<" "<<H[rt]<<endl;        return H[rt];    }    else {        int mid=(L+R)>>1;        if(lazy[rt]) {            pushdown(rt,L,R);            //cout<<"pushdown: "<<L<<" "<<R<<endl;        }        if(r<=mid) return query(rt*2,L,mid,l,r);        else if(l>mid) return query(2*rt+1,mid+1,R,l,r);        else {            LL a=query(2*rt,L,mid,l,mid);            LL b=query(2*rt+1,mid+1,R,mid+1,r);            return (a*pw[r-mid] % MOD + b) % MOD;           }    }}bool check(int L,int R,int d){    if(d>=R-L+1) return true;    return query(1,1,n,L,R-d)==query(1,1,n,L+d,R);}char ss[N];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int m,k;    scanf("%d%d%d",&n,&m,&k);    init();    scanf("%s",ss+1);    for(int i=1;i<=n;i++) {        update(1,1,n,i,i,ss[i]-'0'+1);    }    m+=k;    while(m--){        int tp,l,r,d;        scanf("%d%d%d%d",&tp,&l,&r,&d);        if(tp == 1){            update(1,1,n,l,r,d+1);        }        else {            printf("%s\n", check(l,r,d)?"YES":"NO");        }    }    //system("pause");    return 0;}

还有队友写的一种风格,Orz

#include <bits/stdc++.h>#define ll long long#define ull unsigned long longusing namespace std;const int MAXN = 100000+50; const int P = 1e9+7;int n, m, k;int p[MAXN], ch[10][MAXN];struct Node{    int l, r, h, len, lazy;    int mid() {        return (l + r) / 2;    }    void pushdown(int v) {        lazy = v;        h = ch[v][len];    }}tree[MAXN*4];int merge(int h1, int h2, int len){//  cout << h1 << ' ' << h2 << ' ' << len << endl;    if (len > 0)        return (h1 + (ll)h2 * p[len] % P) % P;    else        return h2;}void build(int l, int r, int idx){    tree[idx].l = l;    tree[idx].r = r;    tree[idx].len = (r - l + 1);    tree[idx].lazy = -1;    if (l == r) {        tree[idx].h = getchar() - '0';        return;    }    int mid = tree[idx].mid();    build(l, mid, idx*2);    build(mid+1, r, idx*2+1);    tree[idx].h = merge(tree[idx*2].h, tree[idx*2+1].h, tree[idx*2].len);//  cout << l << ' ' << r   << ' ' << tree[idx]. h << endl;}void update(int l, int r, int v, int idx){    if (l > r)        return;    if (l == tree[idx].l && r == tree[idx].r) {        tree[idx].pushdown(v);        tree[idx].lazy = v;        return;    }    if (tree[idx].lazy != -1) {        tree[idx*2].pushdown(tree[idx].lazy);        tree[idx*2+1].pushdown(tree[idx].lazy);        tree[idx].lazy = -1;    }    int mid = tree[idx].mid();    update(l, min(mid, r), v, idx*2);    update(max(mid+1, l), r, v, idx*2+1);    tree[idx].h = merge(tree[idx*2].h, tree[idx*2+1].h, tree[idx*2].len);}int query(int l, int r, int idx){    if (l > r)        return 0;    if (l == tree[idx].l && r == tree[idx].r) {        return tree[idx].h;    }    if (tree[idx].lazy != -1) {        tree[idx*2].pushdown(tree[idx].lazy);        tree[idx*2+1].pushdown(tree[idx].lazy);        tree[idx].lazy = -1;    }    int mid = tree[idx].mid();    return merge(query(l, min(r, mid), idx*2), query(max(mid+1, l), r, idx*2+1), min(mid, r)-l+1);}int main(){    scanf("%d%d%d", &n, &m, &k);    m += k;    p[0] = 1;    for (int i = 1; i < n; i++)        p[i] = (ll)p[i-1] * 451309 % P;    for (int i = 0; i < 10; i++) {        for (int j = 1; j <= n; j++)            ch[i][j] = (ch[i][j-1] + (ll)i * p[j-1] % P) % P;    }    getchar();    build(1, n, 1);    while (m--) {        int a, b, c, d;        scanf("%d%d%d%d", &a, &b, &c, &d);        if (a == 1)            update(b, c, d, 1);        else            printf("%s\n", query(b, c-d, 1) == query(b+d, c, 1) ? "YES" : "NO");    }    return 0;}
0 0
原创粉丝点击