天天看點

Luogu P2633 Count on a tree

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define
#define

using namespace std;
typedef long long ll;
struct node {
    int next, to;
}edge[A];
struct OO {
    int l, r, w;
}tree[A << 4];
int head[A], num_edge;
void add_edge(int from, int to) {
    edge[++num_edge].next = head[from];
    edge[num_edge].to = to;
    head[from] = num_edge;
}
vector<int> v;
int n, m, a[A], b[A], x, y, z, cnt, tot, k;
int siz[A], dep[A], fa[A], son[A], top[A], tp, dfn[A], pre[A], root[A << 4];
void prepare(int fr) {
    siz[fr] = 1;
    for (int i = head[fr]; i; i = edge[i].next) {
        int ca = edge[i].to;
        if (ca == fa[fr]) continue;
        fa[ca] = fr;
        dep[ca] = dep[fr] + 1;
        prepare(ca);
        siz[fr] += siz[ca];
        if (siz[ca] > siz[son[fr]]) son[fr] = ca;
    }
}
void dfs(int fr, int tp) {
    dfn[fr] = ++cnt, pre[cnt] = fr, top[fr] = tp;
    if (!son[fr]) return;
    dfs(son[fr], tp);
    for (int i = head[fr]; i; i = edge[i].next) {
        int ca = edge[i].to;
        if (ca == fa[fr] or ca == son[fr]) continue;
        dfs(ca, ca);
    }
}
int lca(int x, int y) {
    while (top[x] != top[y])
        if (dep[top[x]] >= dep[top[y]])
            x = fa[top[x]];
        else y = fa[top[y]];
    return dep[x] < dep[y] ? x : y;
}
void build(int &k, int l, int r) {
    k = ++tot;
    tree[k].w = 0;
    if (l == r) return;
    int m = (l + r) >> 1;
    build(tree[k].l, l, m);
    build(tree[k].r, m + 1, r);
}
void change(int l, int r, int &x, int &y, int k) {
    tree[++tot] = tree[y];
    tree[tot].w++;
    x = tot;
    if (l == r) return;
    int m = (l + r) >> 1;
    if (k <= m) change(l, m, tree[x].l, tree[y].l, k);
    else change(m + 1, r, tree[x].r, tree[y].r, k);
}
int query(int t1, int t2, int t3, int t4, int l, int r, int k) {
    if (l == r) return l;
    int m = (l + r) >> 1; //看要往哪邊走
    int xx = tree[tree[t2].l].w + tree[tree[t1].l].w - tree[tree[t3].l].w - tree[tree[t4].l].w;
    if (k <= xx) return query(tree[t1].l, tree[t2].l, tree[t3].l, tree[t4].l, l, m, k);
    else return query(tree[t1].r, tree[t2].r, tree[t3].r, tree[t4].r, m + 1, r, k - xx);
}
void open(int fr, int faa) { //沿用faa建自己
    change(1, v.size(), root[fr], root[faa], a[fr]);
    for (int i = head[fr]; i; i = edge[i].next) {
        int ca = edge[i].to;
        if (ca == fa[fr]) continue;
        open(ca, fr);
    }
}

int main(int argc, char const *argv[]) {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        v.push_back(a[i]);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    build(root[0], 1, v.size());
    for (int i = 1; i <= n; i++) a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
    for (int i = 1; i < n; i++) {
        scanf("%d%d", &x, &y);
        add_edge(x, y);
        add_edge(y, x);
    }
    dep[1] = 1; prepare(1); dfs(1, 1);
    open(1, 0);
    int ans = 0;
    for (int i = 1; i <= m; i++) {
        scanf("%d%d%d", &x, &y, &k); x ^= ans;
        int ll = lca(x, y);
        int xx = v[query(root[x], root[y], root[ll], root[fa[ll]], 1, v.size(), k) - 1];
        printf("%d\n", xx);
        ans = xx;
    }
}