原题链接
- 题意:一棵树,每个点上有点权,然后求简单路径上第 \(k\) 小。
- 题解:用的朴素做法,看到静态第 \(k\) 小,就用了主席树,然后在图上操作,要感性理解一下,用 \(lca\),即用 \(u,v\) 的版本然后剪掉双倍 \(lca\) 注意因为 \(lca\) 本身是包括的所以不要剪两倍的 \(lca\) 所以就是,每次剪掉 \(fa[lca][0]\) 和 \(lca\) 这两棵树的就可以了。
- 代码:
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
const int N = 2e5 * 20;
int a[N], b[N], root[N], nn, dep[N];
struct President_Tree {
int idx;
struct node {
int l, r, data;
}tr[N];
inline void create(int &p, int q, int l, int r, int num){
p = ++idx;tr[p] = tr[q];tr[p].data++;
if (l == r)return;
int mid = l + r >> 1;
if (num <= mid)create(tr[p].l, tr[q].l, l, mid, num);
else create(tr[p].r, tr[q].r, mid+1, r, num);
}
inline int ask(int u, int v, int fa, int faa, int l, int r, int num) {
int cnt = tr[tr[u].l].data + tr[tr[v].l].data - tr[tr[fa].l].data - tr[tr[faa].l].data;
int mid = l + r >> 1;
if (l == r)return r;
if (num <= cnt)return ask(tr[u].l, tr[v].l, tr[fa].l, tr[faa].l, l, mid, num);
else return ask(tr[u].r, tr[v].r, tr[fa].r, tr[faa].r, mid + 1, r, num-cnt);
}
}T;
vector<int>G[N];
int f[N][20];
void dfs(int u, int fa) {
T.create(root[u], root[fa], 1, nn, a[u]);
dep[u] = dep[fa] + 1;
f[u][0] = fa;
for (int i = 1; i <= 18; i++) {
f[u][i] = f[f[u][i - 1]][i - 1];
}
for (int i = 0; i < G[u].size(); i ++ ) {
int v = G[u][i];
if (v == fa)continue;
dfs(v, u);
}
return;
}
int Lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = 18; i >= 0; i--) {
if (dep[f[u][i]]>= dep[v])u = f[u][i];
}
if (u ==v)return v;
for (int i = 18; i >=0; i--) {
if (f[u][i] != f[v][i]){
u = f[u][i];v = f[v][i];
}
}
return f[u][0];
}
signed main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++)scanf("%d", &a[i]),b[i] = a[i];
sort(b + 1, b + 1 + n);
nn = unique(b + 1, b + 1 + n) - b - 1;
for (int i = 1; i <= n; i ++)a[i] = lower_bound(b + 1, b + 1 + nn, a[i]) - b;
for (int i = 1; i < n; i ++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, 0);
for (int i = 1; i <= m; i ++) {
int u, v, k;
scanf("%d%d%d", &u, &v, &k);
int lca = Lca(u, v);
printf("%d\n", b[T.ask(root[u],root[v], root[lca], root[f[lca][0]], 1,nn, k)]);
}
}