zoukankan      html  css  js  c++  java
  • luoguP4715 [英语]Z语言 平衡树+hash

    显然只能有$hash$来做....

    我们需要一个东西来维护$sum i * seed^{rank[i]}$

    很自然地联想到平衡树

    如果以序列下标建立一棵平衡树,那么无法处理

    因此,可以以权值为下标建立一棵平衡树,把$rank[i]$拆分成若干个$sz[ls] + 1$即可维护

    具体而言,记$pos[i]$表示$i$号节点的位置,$sum[i]$表示平衡树中$i$号节点的子树形成的$hash$值

    那么,$sum[i] = pos[i] * seed^{sz[ls] + 1} + sum[ls] + sum[rs] * seed^{sz[ls] + 1}$

    首先预处理出所有$A$串的$hash$值,存进$map$中

    处理时,注意$[1, m]$和$[2, m + 1]$的串在平衡树中的$hash$值会有一个增量的区别

    由于元素两两不同,因此可以确定增量为$sum seed^i$

    之后,每次动态地维护$B$串的$hash$值,查询即可

    下面的代码由于插入了$-1$,因此更新时略有不同...

    复杂度$O(n log n)$

    #include <map>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    #define ll long long
    #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; char c = gc();
        while(c > '9' || c < '0') c = gc();
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p;
    }
    
    const int sid = 500050;
    const int seed = 19260817;
    
    ll val[sid];
    map <ull, int> ans;
    int n, m, q, rt, id, A[sid], B[sid];
    ull pos[sid], sum[sid], wei[sid];
    int s[sid][2], sz[sid], fa[sid];
    
    inline bool isrc(int o) {
        return s[fa[o]][1] == o;
    }
    
    inline void upd(int o) {
        int ls = s[o][0], rs = s[o][1];
        sz[o] = sz[ls] + sz[rs] + 1;
        sum[o] = wei[sz[ls]] * pos[o] + sum[ls] + wei[sz[ls] + 1] * sum[rs];
    }
    
    inline void rotate(int o) {
        int f = fa[o], g = fa[f];
        int ro = isrc(o), rf = isrc(f);
        fa[o] = g; if(g) s[g][rf] = o;
        s[f][ro] = s[o][ro ^ 1];
        fa[f] = o; fa[s[o][ro ^ 1]] = f;
        s[o][ro ^ 1] = f; upd(f); upd(o);
    }
    
    inline void splay(int o, int tar) {
        while(fa[o] != tar) {
            int f = fa[o], g = fa[f];
            if(g != tar) rotate(isrc(o) == isrc(f) ? f : o);
            rotate(o);
        }
        if(!tar) rt = o;
    }
    
    inline void insert(ll v, int w) {
        int o = rt, f = 0;
        while(o) f = o, o = s[o][v > val[o]];
        o = ++ id; 
        if(f) s[f][v > val[f]] = o;
        fa[o] = f; sz[o] = 1; val[o] = v;
        pos[o] = w; sum[o] = w;
        splay(o, 0);
    }
    
    inline void find(ll v) {
        int o = rt;
        while(s[o][v > val[o]] && val[o] != v)
            o = s[o][v > val[o]];
        splay(o, 0);
    }
    
    inline void erase(int v) {
        find(v);
        int pre = s[rt][0], suf = s[rt][1];
        while(s[pre][1]) pre = s[pre][1];
        while(s[suf][0]) suf = s[suf][0];
        splay(pre, 0); splay(suf, pre);
        s[suf][0] = 0; 
        if(suf) upd(suf); 
        if(pre) upd(pre);
    }
    
    inline void Hash() {
        ull exa = 0; wei[0] = 1;
        rep(i, 1, m + 5) wei[i] = wei[i - 1] * seed;
        rep(i, 1, m) exa += wei[i];
        
        insert(-1, 0); insert(2147483648, 0);
        rep(i, 1, m) insert(A[i], i);
        rep(i, m, n) {
            ans[sum[rt] - exa * (i - m)] ++;
            if(i == n) break;
            erase(A[i - m + 1]);
            insert(A[i + 1], i + 1);
        }
        rt = 0;
        rep(i, 1, id) {
            s[i][0] = s[i][1] = sz[i] = 0;
            val[i] = sum[i] = fa[i] = 0;
        }
        id = 0;
    }
    
    int main() {
        n = read(); m = read(); q = read();
        rep(i, 1, n) A[i] = read();
        Hash();
        insert(-1, 0); insert(2147483648, 0);
        rep(i, 1, m) B[i] = read();
        rep(i, 1, m) insert(B[i], i);
        rep(i, 1, q) {
            int x = read(), c = read();
            erase(B[x]); 
            insert(B[x] = c, x);
            printf("%d
    ", ans[sum[rt]]);
        }
        return 0;
    }
  • 相关阅读:
    使用Ansible安装部署nginx+php+mysql之安装php(2)
    使用Ansible安装部署nginx+php+mysql之安装nginx(1)
    Ansible常见问题处理
    4.2、Ansible常用模块
    3.2、Ansible单命令测试
    2、Ansible配置文件详解
    4.1、Ansible模块
    3.3、Ansible命令参数详解
    3.1、Ansible命令简要说明及初步使用
    1、Ansible初识简要介绍及安装
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9951579.html
Copyright © 2011-2022 走看看