• 4539: [Hnoi2016]树


    4539: [Hnoi2016]树

    链接

    分析:

      主席树+倍增。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    #define pa pair<int,int>
    using namespace std;
    typedef long long LL;
    #define int 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 = 100005;
    struct Edge { int to, nxt; } e[N << 1];
    struct OPT { int l, r, fa, rt; } q[N];
    int head[N], dfn[N], st[N], ed[N], pos[N], fa[N][20], siz[N], f[N][20], g[N][20], d1[N], d2[N];
    set< pa > s;
    int En, Index, NowIndex, n;
    
    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;
    }
    struct SegmentTree{
        int sum[N * 20], ls[N * 20], rs[N * 20], Root[N], TreeIndex;
        void Insert(int l,int r,int &now,int pre,int p) {
            if (!now) now = ++TreeIndex;
            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 H,int T,int k) {
            if (l == r) return l;
            int mid = (l + r) >> 1;
            if (k <= sum[ls[T]] - sum[ls[H]]) return query(l, mid, ls[H], ls[T], k);
            else return query(mid + 1, r, rs[H], rs[T], k - (sum[ls[T]] - sum[ls[H]]));
        }
    }T;
    void dfs(int u) {
        d1[u] = d1[fa[u][0]] + 1;
        st[u] = ++Index; pos[Index] = u; siz[u] = 1;
        for (int i = 1; i <= 19; ++i) fa[u][i] = fa[fa[u][i - 1]][i - 1];
        for (int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if (v == fa[u][0]) continue;
            fa[v][0] = u;
            dfs(v);
            siz[u] += siz[v];
        }
        ed[u] = Index;
    }
    int LCA1(int u,int v) {
        if (d1[u] < d1[v]) swap(u, v);
        int d = d1[u] - d1[v];
        for (int i = 19; ~i; --i) if ((d >> i) & 1) u = fa[u][i];
        if (u == v) return u;
        for (int i = 19; ~i; --i) if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
        return fa[u][0];
    }
    int getdis(int x,int y) {
        return d1[x] + d1[y] - d1[LCA1(x, y)] * 2;
    }
    void add(int id) {
        int x = read(), y = read(), z;
        q[id].l = NowIndex, q[id].r = (NowIndex += siz[x]) - 1, q[id].rt = x;
        set< pa > :: iterator it = s.lower_bound(pa(y, 0)); z = q[it->second].rt;
        q[id].fa = T.query(1, n, T.Root[st[z] - 1], T.Root[ed[z]], y - q[it->second].l + 1);
        f[id][0] = it->second, g[id][0] = getdis(q[id].fa, z) + 1;
        d2[id] = d2[it->second] + 1;
        for (int i = 1; i <= 19; ++i) f[id][i] = f[f[id][i - 1]][i - 1], g[id][i] = g[id][i - 1] + g[f[id][i - 1]][i - 1];
        s.insert(pa(q[id].r, id));
    }
    int LCA2(int u,int v,int tu,int tv) {
        if (d2[u] < d2[v]) swap(u, v), swap(tu, tv);
        int ans = 0, t = u, d = d2[u] - d2[v];
        for (int i = 19; ~i; --i) if ((d >> i) & 1) ans += g[u][i], u = f[u][i];
        if (u == v) {
            d --; ans = 0; u = t; 
            for (int i = 19; ~i; --i) if ((d >> i) & 1) ans += g[t][i], t = f[t][i];
            ans += getdis(q[t].fa, tv) + 1 + getdis(tu, q[u].rt);
            return ans;
        }
        ans += getdis(tu, q[t].rt) + getdis(tv, q[v].rt);
        for (int i = 19; ~i; --i) if (f[u][i] != f[v][i]) ans += g[u][i] + g[v][i], u = f[u][i], v = f[v][i];
        ans += getdis(q[u].fa, q[v].fa) + 2;
        return ans;
    }
    void Ask() {
        int u = read(), v = read(), ans, iu, iv, tu, tv;
        iu = s.lower_bound(pa(u, 0))->second, iv = s.lower_bound(pa(v, 0))->second;
        tu = T.query(1, n, T.Root[st[q[iu].rt] - 1], T.Root[ed[q[iu].rt]], u - q[iu].l + 1);
        tv = T.query(1, n, T.Root[st[q[iv].rt] - 1], T.Root[ed[q[iv].rt]], v - q[iv].l + 1);
        if (iu != iv) ans = LCA2(iu, iv, tu, tv);
        else ans = getdis(tu, tv);    
        printf("%lld
    ", ans);
    }
    signed main() {
        n = read();int m = read(), Q = read();
        for (int i = 1; i < n; ++i) add_edge(read(), read());
        dfs(1);
        for (int i = 1; i <= n; ++i) 
            T.Insert(1, n, T.Root[i], T.Root[i - 1], pos[i]);
        NowIndex = n + 1;
        s.insert(pa(n, 1)); q[1].l = 1, q[1].r = n, q[1].rt = 1, q[1].fa = 0;
        for (int i = 1; i <= m; ++i) add(i + 1);
        while (Q --) Ask();
        return 0;
    }
  • 相关阅读:
    yum只下载不安装的方法
    在VS2008下编译Qt4.4.x
    Linux sh脚本异常:bad interpreter: No such file or directory
    动态链接库dll,静态链接库lib, 导入库lib 转
    Accumulation Buffer(累积缓存)
    mysql中ip和整数的转换
    开车撞人了!
    windows 下getc()返回0x1A表示EOF
    NPC问题
    关于普华永道、麦肯锡和IBM的笑话
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10513754.html
Copyright © 2020-2023  润新知