【模板】数据结构

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
    }
}

 

你可能感兴趣的:(【模板】数据结构)