zoukankan      html  css  js  c++  java
  • [SDOI 2013]森林

    Description

    题库链接

    给你 (n) 个节点,初始 (m) 条边, (t) 组操作。让你支持:

    1. 询问树上路径点权 (K) 小;
    2. 支持加边操作。

    强制在线,所有状态保证是一个树(森林)。

    (1leq n,m,tleq 8cdot 10^4)

    Solution

    分别考虑这道题的两个子问题,显然一个是主席树的板子,另一个是 (LCT) 的板子。

    这两者不好结合,干脆丢掉一个。

    查询 (K) 小,暴力的话显然是不可行的。但动态连边我们是可以用启发式合并将复杂度均摊成 (log)

    总复杂度 (O(nlog_2^2 n)) ,是可行的。

    Code

    //It is made by Awson on 2018.3.15
    #include <bits/stdc++.h>
    #define LL long long
    #define dob complex<double>
    #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
    #define writeln(x) (write(x), putchar('
    '))
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int N = 8e4;
    void read(int &x) {
        char ch; bool flag = 0;
        for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
        for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
        x *= 1-2*flag;
    }
    void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
    void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); }
    
    int n, lim, m, t, a[N+5], b[N+5], tot, u, v, k, fa[N+5], pa[N+5], size[N+5], dep[N+5], f[N+5][20];
    struct tt {int to, next; }edge[(N<<1)+5];
    int path[N+5], top, last; char ch[5];
    struct Segment_tree {
        int root[N+5], ch[N*120+5][2], key[N*120+5], pos;
        int cpynode(int o) {++pos, ch[pos][0] = ch[o][0], ch[pos][1] = ch[o][1], key[pos] = key[o]; return pos; }
        void insert(int &o, int l, int r, int loc) {
        o = cpynode(o); ++key[o];
        if (l == r) return; int mid = (l+r)>>1;
        if (loc <= mid) insert(ch[o][0], l, mid, loc); else insert(ch[o][1], mid+1, r, loc);
        }
        int query(int a, int b, int c, int d, int l, int r, int k) {
        if (l == r) return l; int mid = (l+r)>>1;
        int tmp = key[ch[a][0]]+key[ch[b][0]]-key[ch[c][0]]-key[ch[d][0]];
        if (tmp >= k) return query(ch[a][0], ch[b][0], ch[c][0], ch[d][0], l, mid, k);
        else return query(ch[a][1], ch[b][1], ch[c][1], ch[d][1], mid+1, r, k-tmp);
        }
    }T;
    
    void clear(int o) {
        dep[o] = 0;
        for (int i = path[o]; i; i = edge[i].next)
        if (dep[edge[i].to]) clear(edge[i].to);
    }
    void dfs(int o, int pare, int father, int depth) {
        T.root[o] = T.root[father]; T.insert(T.root[o], 1, tot, lower_bound(b+1, b+tot+1, a[o])-b);
        dep[o] = depth, pa[o] = f[o][0] = father; ++size[pare];
        for (int i = 1; i <= lim; i++) f[o][i] = f[f[o][i-1]][i-1];
        for (int i = path[o]; i; i = edge[i].next)
        if (!dep[edge[i].to]) dfs(edge[i].to, pare, o, depth+1);
    }
    int query(int u, int v) {
        if (dep[u] < dep[v]) Swap(u, v);
        for (int i = lim; i >= 0; i--) if (dep[f[u][i]] >= dep[v]) u = f[u][i];
        if (u == v) return u;
        for (int i = lim; i >= 0; i--) if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
        return f[u][0];
    }
    int find(int x) {return fa[x] ? fa[x] = find(fa[x]) : x; }
    void add(int u, int v) {edge[++top].to = v, edge[top].next = path[u], path[u] = top; }
    void work() {
        int testcase; read(testcase);
        read(n), read(m), read(t); lim = log(n)/log(2);
        for (int i = 1; i <= n; i++) read(a[i]), b[i] = a[i];
        sort(b+1, b+n+1);
        tot = unique(b+1, b+n+1)-b-1;
        for (int i = 1; i <= m; i++) read(u), read(v), add(u, v), add(v, u), fa[find(u)] = find(v);
        for (int i = 1; i <= n; i++) if (fa[i] == 0) dfs(i, i, 0, 1);
        while (t--) {
        scanf("%s", ch); read(u), u ^= last, read(v), v ^= last;
        if (ch[0] == 'Q') read(k), k ^= last, m = query(u, v), writeln(last = b[T.query(T.root[u], T.root[v], T.root[m], T.root[pa[m]], 1, tot, k)]);
        else {
            if (size[find(u)] < size[find(v)]) Swap(u, v); clear(v);
            add(u, v), add(v, u); fa[find(v)] = find(u);
            dfs(v, find(u), u, dep[u]+1);
        }
        }
    }
    int main() {
        work(); return 0;
    }
  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8572179.html
Copyright © 2011-2022 走看看