「luogu2633」Count on a tree

与世无争的帅哥 提交于 2020-01-23 23:42:42

「luogu2633」Count on a tree

传送门
树上主席树板子。
每个节点的根从其父节点更新得到,查询的时候差分一下就好了。
参考代码:

#include <algorithm>
#include <cstdio>
#define rg register
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
    s = 0; int f = 0; char c = getchar();
    while ('0' > c || c > '9') f |= c == '-', c = getchar();
    while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
    s = f ? -s : s;
}

const int _ = 1e5 + 5;

int tot, head[_], nxt[_ << 1], ver[_ << 1];
inline void Add_edge(int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; }

int n, q, a[_], X[_];
int dep[_], siz[_], son[_], fa[_], top[_];
int tt, rt[_], lc[_ << 5], rc[_ << 5], cnt[_ << 5];

inline void update(int& p, int q, int v, int l = 1, int r = X[0]) {
    p = ++tt, lc[p] = lc[q], rc[p] = rc[q], cnt[p] = cnt[q] + 1;
    if (l == r) return ;
    int mid = (l + r) >> 1;
    if (v <= mid) update(lc[p], lc[q], v, l, mid);
    else update(rc[p], rc[q], v, mid + 1, r);
}

inline int query(int u, int v, int lca, int flca, int k, int l = 1, int r = X[0]) {
    if (l == r) return l;
    int mid = (l + r) >> 1;
    int num = cnt[lc[u]] + cnt[lc[v]] - cnt[lc[lca]] - cnt[lc[flca]];
    if (num >= k) return query(lc[u], lc[v], lc[lca], lc[flca], k, l, mid);
    else return query(rc[u], rc[v], rc[lca], rc[flca], k - num, mid + 1, r);
}

inline void dfs(int u, int f) {
    dep[u] = dep[f] + 1, siz[u] = 1, fa[u] = f;
    update(rt[u], rt[f], a[u]);
    for (rg int i = head[u]; i; i = nxt[i]) {
        int v = ver[i]; if (v == f) continue ;
        dfs(v, u), siz[u] += siz[v];
        if (siz[son[u]] < siz[v]) son[u] = v;
    }
}

inline void dfs(int u, int f, int topf) {
    top[u] = topf;
    if (son[u]) dfs(son[u], u, topf);
    for (rg int i = head[u]; i; i = nxt[i]) {
        int v = ver[i]; if (v == f || v == son[u]) continue ;
        dfs(v, u, v);
    }
}

inline int LCA(int x, int y) {
    int fx = top[x], fy = top[y];
    while (fx != fy) {
        if (dep[fx] < dep[fy]) swap(fx, fy), swap(x, y);
        x = fa[fx], fx = top[x];
    }
    return dep[x] < dep[y] ? x : y;
}

int main() {
    read(n), read(q);
    for (rg int i = 1; i <= n; ++i) read(a[i]), X[i] = a[i];
    sort(X + 1, X + n + 1);
    X[0] = unique(X + 1, X + n + 1) - X - 1;
    for (rg int i = 1; i <= n; ++i) a[i] = lower_bound(X + 1, X + X[0] + 1, a[i]) - X;
    for (rg int u, v, i = 1; i < n; ++i)
        read(u), read(v), Add_edge(u, v), Add_edge(v, u);
    dfs(1, 0), dfs(1, 0, 1);
    for (rg int ans = 0, u, v, k, lca; q--; ) {
        read(u), u ^= ans, read(v), read(k), lca = LCA(u, v);
        ans = X[query(rt[u], rt[v], rt[lca], rt[fa[lca]], k)], printf("%d\n", ans);
    }
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!