luoguP4036 [JSOI2008]火星人 平衡树+hash

Posted ReMoon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luoguP4036 [JSOI2008]火星人 平衡树+hash相关的知识,希望对你有一定的参考价值。

这个操作十分的复杂

但是可以拿平衡树维护

直接二分答案然后用$hash$值判断即可

复杂度$O(10000 * log^2 n + n \\log n)$

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define ri register int
#define ull unsigned long long
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)
#define gc getchar
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > \'9\' || c < \'0\') { if(c == \'-\') w = -1; c = gc(); }
    while(c >= \'0\' && c <= \'9\') p = p * 10 + c - \'0\', c = gc();
    return p * w;
}

inline char gcr() {
    char c = gc();
    while(1) {
        if(c >= \'a\' && c <= \'z\') return c;
        if(c >= \'A\' && c <= \'Z\') return c;
        c = gc();
    }
}

const int sid = 300005;
const int sed = 19260817;

char s[sid];
int n, m, rt, at, bt, ct, dt, id;
int sz[sid], ls[sid], rs[sid], pri[sid];
ull wei[sid], sum[sid], val[sid];

inline int rand() {
    static int seed = 14123;
    return seed = (1ll * seed * 1919) % 2147483647;
}

inline int newnode(char v) {
    ++ id;
    val[id] = v; sz[id] = 1;
    pri[id] = rand(); sum[id] = v;
    return id;
}

inline void upd(int o) {
    sz[o] = sz[ls[o]] + sz[rs[o]] + 1;
    sum[o] = sum[ls[o]] + sum[rs[o]] * wei[sz[ls[o]] + 1];
    sum[o] += val[o] * wei[sz[ls[o]] + 1];
}

inline int merge(int x, int y) {
    if(!x || !y) return x + y;
    if(pri[x] > pri[y]) {
        rs[x] = merge(rs[x], y);
        upd(x); return x;
    }
    else {
        ls[y] = merge(x, ls[y]);
        upd(y); return y;
    }
}

inline void split(int o, int k, int &x, int &y) {
    if(!o) { x = y = 0; return; }
    if(k <= sz[ls[o]]) y = o, split(ls[o], k, x, ls[o]);
    else x = o, split(rs[o], k - sz[ls[o]] - 1, rs[o], y);
    upd(o);
}

inline ull getHash(int l, int r) {
    split(rt, r, at, bt);
    split(at, l - 1, ct, dt);
    ull ret = sum[dt];
    rt = merge(ct, merge(dt, bt));
    return ret;
}

inline bool check(int x, int y, int v) {
    return getHash(x, x + v - 1) == getHash(y, y + v - 1);
}

int main() {
    scanf("%s", s + 1);
    n = strlen(s + 1);
    
    wei[0] = 1;
    rep(i, 1, 300000) wei[i] = wei[i - 1] * sed;
    rep(i, 1, n) rt = merge(rt, newnode(s[i]));
        
    m = read();
    rep(i, 1, m) {
        char c = gcr();
        int x, y; char d;
        if(c == \'Q\') {
            x = read(); y = read();
            if(x > y) swap(x, y);
            int l = 1, r = n - y + 1, ans = 0;
            while(l <= r) {
                int mid = (l + r) >> 1;
                if(check(x, y, mid)) {
                    l = mid + 1, ans = mid;
                    printf("qaq -> %d\\n", mid);
                }
                else r = mid - 1;
            }
            printf("%d\\n", ans);
        }
        else if(c == \'R\') {
            x = read(); d = gcr();
            split(rt, x - 1, at, bt);
            split(bt, 1, ct, dt);
            rt = merge(at, merge(newnode(d), dt));
        }
        else if(c == \'I\') {
            n ++;
            x = read(); d = gcr();
            split(rt, x, at, bt);
            rt = merge(at, merge(newnode(d), bt));
        }
    }
    return 0;
}

 

以上是关于luoguP4036 [JSOI2008]火星人 平衡树+hash的主要内容,如果未能解决你的问题,请参考以下文章

[JSOI2008] 火星人

1014: [JSOI2008]火星人prefix

bzoj1014[JSOI2008]火星人prefix

bzoj1014: [JSOI2008]火星人prefix

[JSOI2008]火星人prefix

[JSOI2008]火星人