zoukankan      html  css  js  c++  java
  • P3302 [SDOI2013]森林

    P3302 [SDOI2013]森林

    链接

    分析:

      每个点建立从当前点向根的主席树,那么可以查询了。

      考虑修改,启发式合并!

      开O2才能过。。。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    #include<stack>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 80005, Log = 17;
    struct Edge { int to, nxt; } e[350005];
    int head[N], fa[N], f[N][18], disc[N], w[N], siz[N], dep[N], En, Cnt = 1;
    int Root[N], sum[N * 300], ls[N * 300], rs[N * 300], Index;
    
    inline void add_edge(int u,int v) {
        ++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En;
        ++En; e[En].to = u, e[En].nxt = head[v]; head[v] = En;
    }
    void Insert(int l,int r,int &now,int pre,int p) {
        if (!now) now = ++Index;
        sum[now] = sum[pre] + 1;
        if (l == r) return ;
        int mid = (l + r) >> 1;
        if (p <= mid) {
            rs[now] = rs[pre];
            Insert(l, mid, ls[now], ls[pre], p);
        }
        else {
            ls[now] = ls[pre];
            Insert(mid + 1, r, rs[now], rs[pre], p);
        }
    }
    int query(int l,int r,int x,int y,int p1,int p2,int k) {
        if (l == r) return disc[l];
        int mid = (l + r) >> 1;
        int t = sum[ls[x]] + sum[ls[y]] - sum[ls[p1]] - sum[ls[p2]];
        if (k <= t) return query(l, mid, ls[x], ls[y], ls[p1], ls[p2], k);
        else return query(mid + 1, r, rs[x], rs[y], rs[p1], rs[p2], k - t);
    }
    int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
    void dfs(int u,int top) {
        for (int i = 1; i <= Log; ++i) f[u][i] = f[f[u][i - 1]][i - 1];
        siz[top] ++;
        fa[u] = top;
        dep[u] = dep[f[u][0]] + 1;
        Insert(1, Cnt, Root[u], Root[f[u][0]], w[u]);
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (v == f[u][0]) continue;
            f[v][0] = u;
            dfs(v, top);
        }
    }
    int LCA(int u,int v) {
        if (dep[u] < dep[v]) swap(u, v);
        int d = dep[u] - dep[v];
        for (int i = Log; ~i; --i) if ((d >> i) & 1) u = f[u][i];
        if (u == v) return u;
        for (int i = Log; ~i; --i) 
            if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
        return f[u][0];
    }
    int main() {
        read();int n = read(), m = read(), Q = read();
        for (int i = 1; i <= n; ++i) disc[i] = w[i] = read(), fa[i] = i;
        for (int i = 1; i <= m; ++i) {
            int u = read(), v = read();
            add_edge(u, v);
        }
        sort(disc + 1, disc + n + 1);
        for (int i = 2; i <= n; ++i) if (disc[i] != disc[Cnt]) disc[++Cnt] = disc[i];
        for (int i = 1; i <= n; ++i) w[i] = lower_bound(disc + 1, disc + Cnt + 1, w[i]) - disc;
        for (int i = 1; i <= n; ++i) if (!dep[i]) dfs(i, i); 
        
        int ans = 0;char opt[10];
        while (Q --) {
            scanf("%s", opt);
            if (opt[0] == 'Q') {
                int x = read() ^ ans, y = read() ^ ans, k = read() ^ ans;
                int lca = LCA(x, y);
                printf("%d
    ", ans = query(1, Cnt, Root[x], Root[y], Root[lca], Root[f[lca][0]], k));
            }
            else {
                int x = read() ^ ans, y = read() ^ ans;
                add_edge(x, y);
                int fx = find(x), fy = find(y);
                if (siz[fx] > siz[fy]) swap(fx, fy), swap(x, y);
                f[y][0] = x;
                dfs(y, fx);
            }
        }
        return 0;
    }
  • 相关阅读:
    将博客搬至CSDN
    vector iterator not incrementable For information on how your program can cause an an assertion Failure, see the Visual c + + documentation on asserts
    VS2013+opencv2.4.9配置
    数组去重排序
    堆排序理解 完整代码
    dijkstra 两点的最短路径 单源 最短路径
    欧拉回路
    next 前缀字符串
    继续畅通工程
    sql server转移tempdb数据库的物理存放位置
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10341487.html
Copyright © 2011-2022 走看看