zoukankan      html  css  js  c++  java
  • 【模板】数据结构

    1 并查集 (不封装,按秩合并)

    int ancestor(int x) {return p[x] == x ? x : (p[x] = ancestor(p[x]));}
    
    bool test(int x, int y, bool un = false) {
        if ((x = ancestor(x)) == (y = ancestor(y))) return true;
        if (un) size[x] > size[y] ? std::swap(x, y) : (void)0, p[x] = y, size[y] += size[x];
        return false;
    }

    2 并查集 (封装)

    struct UFind{
        int sz, *p;
        UFind (): sz(0) {p = NULL;}
        ~UFind () {if(p) delete [] (p);}
        void resize(int size){
            if(p) delete [] (p); p = new int[(sz = size) + 1];
            for(int i = 0; i <= sz; i++) p[i] = i;
        }
        int ancestor(int x) {return x == p[x] ? x : p[x] = ancestor(p[x]);}
        bool test(int x, int y, bool un = false){
            if((x = ancestor(x)) == (y = ancestor(y))) return true;
            if(un) p[x] = y; return false;
        }
    };

    3 树状数组 (不封装)

    #define lowbit(x) (x & -x)
    
    int sum(int h){
        int s = 0;
        while(h){
            s += a[h];
            h -= lowbit(h);
        }
        return s;
    }
    
    int add(int h, int v){
        while(h <= n){
            a[h] += v;
            h += lowbit(h);
        }
        return v;
    }

    4 树状数组 (封装,可清空)

    struct BIT {
        #define lowbit(x) (x & -x)
        int n, ti, tag[N]; ll x[N];
        BIT () : ti(0) {}
        inline void resize(int size) {n = size;}
        inline void clear() {++ti;}
        inline ll & recover(int id) {return tag[id] == ti ? x[id] : (tag[id] = ti, x[id] = 0);}
        ll sum(int h) {ll s = 0; for (; h > 0; h -= lowbit(h)) s += recover(h); return s;}
        void add(int h, ll v) {for (; h <= n; h += lowbit(h)) recover(h) += v;}
    };

    5 线段树 (不封装)

    #define segc int M = L + R - 1 >> 1, lc = id << 1, rc = lc | 1
    
    void add(int id, int L, int R, int h, int v){
        if(L == R) return void(st[id] += v);
        segc; h <= M ? add(lc, L, M, h, v) : add(rc, M + 1, R, h, v);
        x[id].v = x[lc].v + x[rc].v;
    }
    
    int range(int id, int L, int R, int ql, int qr){
        if(ql <= L && qr >= R) return st[id];
        segc, s = 0;
        if(ql <= M) s += range(lc, L, M, ql, min(qr, M));
        if(qr > M) s += range(rc, M + 1, R, max(ql, M + 1), qr);
        return s;
    }

    6 线段树 (封装)

    struct ST{
        #define segc int M = L + R - 1 >> 1, lc = id << 1, rc = lc | 1
        int sz;
        struct node {int v, f; bool zero;} *x;
        ST (): sz(0) {x = NULL;}
        ~ST () {if(x) delete [] (x);}
        void resize(int size) {sz = size; int sz0 = sz << 3; if(x) delete [] (x);
            x = new node[sz0]; memset(x, 0, sz0 * sizeof(node));}
    
        void add(int h, int v) {add(1, 1, sz, h, v);}
        int range(int l, int r) {return query(1, 1, sz, l, r);}
    
        void add(int id, int L, int R, int h, int v){
            if(L == R) return void(x[id].v += v);
            segc; h <= M ? add(lc, L, M, h, v) : add(rc, M + 1, R, h, v);
            x[id].v = x[lc].v + x[rc].v;
        }
    
        int query(int id, int L, int R, int ql, int qr){
            if(ql <= L && R <= qr) return x[id].v;
            segc, s = 0;
            if(ql <= M) s += query(lc, L, M, ql, min(qr, M));
            if(qr > M) s += query(rc, M + 1, R, max(ql, M + 1), qr);
            return s;
        }
    };

    7 可持久化线段树 (add 操作)

    int add(int _id, int L, int R, int h, int v){
        int id = ++cnt; x[id] = x[_id]; x[id].v += v;
        if(L == R) return id;
        int M = L + R - 1 >> 1;
        if(h <= M) x[id].lc = add(x[id].lc, L, M, h, v);
        else x[id].rc = add(x[id].rc, M + 1, R, h, v);
        return id;
    }

    8 伸展树 (Splay)

    #define pa p[nd]
    #define root nd[0].c[0]
    struct node {int v, sz, p, c[2]; ll sum;} nd[N];
    
    inline int dir(int x) {return x == x[nd].pa.c[1];}
    
    inline void update(int x){
        x[nd].sz = x[nd].c[0][nd].sz + x[nd].c[1][nd].sz + 1;
        x[nd].sum = x[nd].c[0][nd].sum + x[nd].c[1][nd].sum + x[nd].v;
    }
    
    void rotate(int x){
        int y = x[nd].p, d = !dir(x);
        nd[y[nd].c[!d] = x[nd].c[d]].p = y;
        x[nd].p = y[nd].p;
        y[nd].pa.c[dir(y)] = x;
        nd[x[nd].c[d] = y].p = x;
        update(y);
    }
    
    void splay(int x, int g = 0){
        for(; x[nd].p != g; rotate(x))
            if(x[nd].pa.p != g) rotate(dir(x) ^ dir(x[nd].p) ? x : x[nd].p);
        update(x);
    }
    
    void insert(int x){
        int y = 0, d = 0;
        if(root) for(y = root; d = (val[x] < y[nd].v), y[nd].c[d]; y = y[nd].c[d]);
        y[nd].c[d] = x;
        nd[x].v = nd[x].sum = val[x]; nd[x].sz = 1; nd[x].p = y; nd[x].c[0] = nd[x].c[1] = 0;
        splay(x);
    }
    
    void erase(int x){
        if(x[nd].p) splay(x);
        if(!(x[nd].c[0] && x[nd].c[1])){
            int d = (x[nd].c[1] > 0);
            x[nd].c[d][nd].p = 0;
            root = x[nd].c[d];
        }else{
            int y;
            for(y = x[nd].c[1]; y[nd].c[0]; y = y[nd].c[0]);
            splay(y, x);
            nd[y[nd].c[0] = x[nd].c[0]].p = y;
            y[nd].p = 0; root = y;
            update(y);
        }
    }
    
    int kth(int x, int v){
        if(x[nd].sz < v) return -1;
        for(int j; ; ){
            j = x[nd].c[0][nd].sz;
            if(v == j + 1) return x;
            x = x[nd].c[v > j]; v > j ? (v -= j + 1) : v;
        }
    }

    9 动态树 (Link-Cut Tree)

    namespace LCT {
        #define pa p[nd]
        struct node {bool rev; int v, p, c[2];} nd[N];
        inline int dir(int x) {return !nd[x].p ? -1 : x == nd[x].pa.c[0] ? 0 : x == nd[x].pa.c[1] ? 1 : -1;}
        inline void reverse(int x) {x && (std::swap(nd[x].c[0], nd[x].c[1]), nd[x].rev = !nd[x].rev);}
        void push_down(int x) {if (nd[x].rev) reverse(nd[x].c[0]), reverse(nd[x].c[1]), nd[x].rev = false;}
        void pull_down(int x) {if (~dir(x)) pull_down(nd[x].p); push_down(x);}
        inline void update(int x) {const int l = nd[x].c[0], r = nd[x].c[1]; nd[x].v = (l ? nd[l].v : 0) + (r ? nd[r].v : 0);}
        void rotate(int x) {
            int y = nd[x].p, d = !dir(x);
            nd[nd[y].c[!d] = nd[x].c[d]].p = y;
            nd[x].p = nd[y].p;
            if (~dir(y)) nd[y].pa.c[dir(y)] = x;
            nd[nd[x].c[d] = y].p = x;
            update(y);
        }
        void splay(int x) {for (pull_down(x); ~dir(x); rotate(x)) if (~dir(nd[x].p)) rotate(dir(x) ^ dir(nd[x].p) ? x : nd[x].p); update(x);}
        void access(int x) {for (int y = 0; x; y = x, x = nd[x].p) splay(x), nd[x].c[1] = y, update(x);}
        void make_root(int x) {access(x), splay(x), reverse(x);}
        int find_root(int x) {for (access(x), splay(x); push_down(x), nd[x].c[0]; x = nd[x].c[0]); return splay(x), x;}
        int split(int x, int y) {return make_root(x), access(y), splay(y), y;}
        void link(int x, int y) {make_root(x), nd[x].p = y;}
        void cut(int x, int y) {split(x, y), nd[x].p = nd[y].c[0] = 0, update(y);}
        void trylink(int x, int y) {x == y || (split(x, y), ~dir(x)) || (nd[x].p = y);}
        void trycut(int x, int y) {split(x, y), nd[y].c[0] == x && !nd[x].c[1] && (nd[x].p = nd[y].c[0] = 0, update(y), 0);}
    }

    10 树堆 (Treap)

    struct random_t{
        ull seed;
        static const ull multiplier = 0x5deece66dll;;
        static const ull addend = 0xbll;
        static const ull mask = 0xffffffffffffll;
    
        random_t () {char *x = new char; seed = (ull)x; delete x;}
    
        unsigned int next(){
            seed = (seed * multiplier + addend) & mask;
            return seed >> 16;
        }
    
        unsigned int next(unsigned int n){
            return n * (ull)next() >> 32;
        }
    }rnd;
    
    #define pa p[nd]
    #define C(x) c[x][nd]
    #define root nd[0].c[0]
    
    struct node {int v, sz, pt; int c[2], p; unsigned priority;} nd[N];
    int cnt = 0;
    
    inline int dir(int x) {return x == nd[x].pa.c[1];}
    
    inline void update(int x){
        nd[x].sz = nd[x].C(0).sz + nd[x].C(1).sz + nd[x].pt;
    }
    
    void rotate(int x){
        int y = nd[x].p, d = !dir(x);
        nd[nd[y].c[!d] = nd[x].c[d]].p = y;
        nd[x].p = nd[y].p;
        nd[y].pa.c[dir(y)] = x;
        nd[nd[x].c[d] = y].p = x;
        update(y); update(x);
    }
    
    void push_up(int x) {for(; x; x = nd[x].p) update(x);}
    
    void rotation(int x) {for(; nd[x].p && nd[x].priority < nd[x].pa.priority; ) rotate(x);}
    
    void insert(int v){
        int x = 0, y = 0, d = 0;
        if(root) for(y = root; nd[y].v != v && nd[y].c[d = v > nd[y].v]; y = nd[y].c[d]);
        if(nd[y].v == v) {++nd[y].pt; push_up(y); return;}
        nd[y].c[d] = x = ++cnt;
        nd[x].v = v; nd[x].sz = nd[x].pt = 1; nd[x].p = y; nd[x].c[0] = nd[x].c[1] = 0;
        nd[x].priority = rnd.next(); push_up(y);
        rotation(x);
    }
    
    void erase(int v){
        int x = 0, y = 0, d = 0;
        if(root) for(x = root; nd[x].v != v && nd[x].c[d = v > nd[x].v]; x = nd[x].c[d]);
        if(nd[x].v != v) return;
        if(nd[x].pt > 1) {--nd[x].pt; push_up(x); return;}
        for(; nd[x].c[0] && nd[x].c[1]; rotate(nd[x].c[d]))
            d = nd[x].C(0).priority > nd[x].C(1).priority;
        d = nd[x].c[1] > 0; y = nd[x].c[d];
        nd[y].p = nd[x].p; nd[x].pa.c[dir(x)] = y; push_up(nd[y].p);
    }
    
    int rank(int v){
        int x = 0, d = 0, k = 0;
        if(root) for(x = root; nd[x].v != v && nd[x].c[d = v > nd[x].v]; x = nd[x].c[d])
            if(d) k += nd[x].C(0).sz + nd[x].pt;
        if(nd[x].v != v) return -1;
        return k + nd[x].C(0).sz;
    }
    
    int kth(int k){
        int x = root;
        if(nd[x].sz < k) return -1;
        for(int j, z; ; ){
            j = nd[x].C(0).sz; z = nd[x].pt;
            if(j <= k && k < j + z) return x;
            x = nd[x].c[k > j]; k > j ? (k -= j + z) : k;
        }
    }
    
    int prev(int v){
        int x = 0, r = -1, d = 0;
        if(root) for(x = root; x; x = nd[x].c[d]) if(d = v > x[nd].v) up(r, nd[x].v); // too little
        return r;
    }
    
    int succ(int v){
        int x = 0, r = INT_MAX, d = 0;
        if(root) for(x = root; x; x = nd[x].c[d]) if(!(d = v >= x[nd].v)) down(r, nd[x].v); // too large
        return r;
    }

    11 析合树 (构造)

    int n, p[N];
    
    namespace DCTree {
        typedef std::pair <int, int> pr;
        const int N = ::N * 2;
    
        enum type {leaf, disjunct, conjunct} I[N];
    
        pr st[20][N];
        int stack1[N], stack2[N], stack[N];
        int cnt, root, left[N], mid[N], right[N];
    
        inline void up(pr &x, const pr &y) {x.first > y.first ? x.first = y.first : 0, x.second < y.second ? x.second = y.second : 0;}
    
        void build_sparse_table() {
            int i, j, k = n; pr *f, *g = *st;
            for (j = 0; 1 << (j + 1) <= n; ++j) {
                f = g, g = st[j + 1], k -= 1 << j;
                for (i = 1; i <= k; ++i)
                    up(g[i] = f[i], f[i + (1 << j)]);
            }
        }
    
        inline bool is_consecutive(int L, int R) {
            int c = lg2(R - L); pr ans = st[c][L]; up(ans, st[c][R - (1 << c)]);
            return ans.second - ans.first == R - L - 1;
        }
    
        namespace ST {
            #define segc int M = (L + R - 1) >> 1, lc = id << 1, rc = lc | 1
            struct node {int v, tag;} x[N * 4];
    
            void build(int id, int L, int R) {
                x[id].v = L, x[id].tag = 0;
                if (L == R) return;
                segc; build(lc, L, M), build(rc, M + 1, R);
            }
    
            void add(int id, int L, int R, int ql, int qr, int v) {
                if (ql <= L && R <= qr) {x[id].v += v, x[id].tag += v; return;}
                segc;
                if (ql <= M) add(lc, L, M, ql, qr, v);
                if (qr > M) add(rc, M + 1, R, ql, qr, v);
                x[id].v = std::min(x[lc].v, x[rc].v) + x[id].tag;
            }
    
            int find_suf(int id, int L, int R, int v, int cv = 0) {
                if (cv + x[id].v > v) return -1;
                if (L == R) return L;
                segc, p = find_suf(lc, L, M, v, cv += x[id].tag);
                return ~p ? p : find_suf(rc, M + 1, R, v, cv);
            }
        }
    
        int pa[N], fc[N], nc[N], deg[N];
    
        inline void link(int x, int px) {pa[x] = px, nc[x] = fc[px], fc[px] = x, ++deg[px];}
    
        void build() {
            int i, l, top1 = 0, top2 = 0, top = 0, &v = root, u; cnt = n;
            for (i = 1; i <= n; ++i) st[0][i] = pr(p[i], p[i]), left[i] = right[i] = i, I[i] = leaf;
            build_sparse_table(), ST::build(1, 1, n);
            for (i = 1; i <= n; ++i) {
                for (; top1 && p[i] > p[ stack1[top1] ]; --top1)
                    ST::add(1, 1, n, stack1[top1 - 1] + 1, stack1[top1], p[i] - p[ stack1[top1] ]);
                for (; top2 && p[i] < p[ stack2[top2] ]; --top2)
                    ST::add(1, 1, n, stack2[top2 - 1] + 1, stack2[top2], p[ stack2[top2] ] - p[i]);
                stack1[++top1] = stack2[++top2] = i;
                l = ST::find_suf(1, 1, n, i);
                for (v = i; top && left[ u = stack[top] ] >= l; --top)
                    if (I[u] == conjunct && is_consecutive(mid[u], i + 1))
                        right[u] = i, link(v, u), v = u;
                    else if (is_consecutive(left[u], i + 1)) {
                        I[++cnt] = conjunct, link(u, cnt), link(v, cnt);
                        left[cnt] = left[u], right[cnt] = i, mid[cnt] = left[v], v = cnt;
                    } else {
                        I[++cnt] = disjunct, link(v, cnt);
                        for (; top && !is_consecutive(left[u], i + 1); --top)
                            link(u, cnt); link(u, cnt);
                        left[cnt] = left[u], right[cnt] = i, v = cnt;
                    }
                stack[++top] = v;
            }
        }
    }

    12 Chtholly  (ODT) / set 维护连续段

    namespace CTree {
        map C;
    
        map::iterator split(int pos) {
            map::iterator it = C.lower_bound(pos), jt = it;
            return it->first == pos ? it : C.emplace_hint(it, pos, (--jt)->second);
        }
    
        void modify(int l, int r, int v) {
            map::iterator it = split(l), jt = split(r), i, j;
            for (j = it; (i = j++) != jt; ) // do something on [i, j]
            C.erase(it, jt), C.emplace(l, v); // do something
        }
    }
  • 相关阅读:
    自动登录跳板机->开发机
    关于写代码的一下规范
    vscode 配置 GOPATH
    thinkphp6.0 nginx 配置
    vue-cli 3.x 构建项目,webpack没有了?
    Laravel6.0 使用 Jwt-auth 实现多用户接口认证
    怎么在 localhost 下访问多个 Laravel 项目,通过一个IP访问多个项目(不仅仅是改变端口哦)
    laravel 5.8 实现消息推送
    vs code 设置 保存自动格式化vue代码
    项目开发规范(编码规范、命名规范、安全规范、前端优化、源码提交规范、代码维护规范、产品发布规范)
  • 原文地址:https://www.cnblogs.com/lau1997/p/12665825.html
Copyright © 2011-2022 走看看