这题和普通的第K大类似。
普通的第K大,是从后往前建立主席树,前一个在后一个的基础上修改。
而树上第K大,依旧是每个结点一棵主席树,是在父节点的基础上修改。
那么可以发现这棵主席树是包括所有祖先结点的(就是深度在当前结点之上的)
查询的时候,是两个结点的值的和,还要减掉lca以上的部分。同时要注意处理lca这个 结点的值。
主要不同便是建树是根据父结点,以前查询的时候注意两个主席树的公共部分。
#include<bits/stdc++.h>
#define M 10000005
#define N 110005
using namespace std;
int n, q, a[N];
vector<int> edge[N];
int t[N], m;
void Init_hash()
{
for (int i = 1; i <= n; i++)
t[i] = a[i];
sort(t + 1, t + 1 + n);
m = unique(t + 1, t + 1 + n) - t - 1;
}
int Hash(int x)
{
return lower_bound(t + 1, t + 1 + m, x) - t;
}
int T[M], lson[M], rson[M], c[M], tot = 0;
int bulid(int l, int r)
{
int root = tot++;
c[root] = 0;
if (l != r)
{
int mid = (l + r) >> 1;
lson[root] = bulid(l, mid);
rson[root] = bulid(mid + 1, r);
}
return root;
}
int update(int root, int pos, int val)
{
int newroot = tot++, tmp = newroot;
c[newroot] = c[root] + val;
int l = 1, r = m;
while (l < r)
{
int mid = (l + r) >> 1;
if (pos <= mid)
{
lson[newroot] = tot++;
rson[newroot] = rson[root];
newroot = lson[newroot];
root = lson[root];
r = mid;
}
else
{
rson[newroot] = tot++;
lson[newroot] = lson[root];
newroot = rson[newroot];
root = rson[root];
l = mid + 1;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int query(int left_root, int right_root, int LCA, int k)
{
int lca_root = T[LCA], pos = Hash(a[LCA]);
int l = 1, r = m;
while (l < r)
{
int mid = (l + r) >> 1;
int t = c[lson[left_root]] + c[lson[right_root]] - 2 * c[lson[lca_root]] + (pos >= l && pos <= mid);
if (t >= k)
{
left_root = lson[left_root];
right_root = lson[right_root];
lca_root = lson[lca_root];
r = mid;
}
else
{
k -= t;
left_root = rson[left_root];
right_root = rson[right_root];
lca_root = rson[lca_root];
l = mid + 1;
}
}
return l;
}
/* 主席树部分 */
/* LCA部分 */
int depth = 0, b[N * 2], cnt = 0;
int p[N], f[N];
void dfs(int u, int pre)
{
int t = ++depth;
b[++cnt] = t;
f[t] = u;
p[u] = cnt;
T[u] = update(T[pre], Hash(a[u]), 1);
for (int i = 0; i < edge[u].size(); i++)
{
int v = edge[u][i];
if (v == pre)
continue;
dfs(v, u);
b[++cnt] = t;
}
}
int dp[N * 2][20];
void Init_rmq(int n)
{
for (int i = 1; i <= n; i++)
dp[i][0] = b[i];
int m = floor(log(n * 1.0) / log(2.0));
for (int j = 1; j <= m; j++)
for (int i = 1; i <= n - (1 << j) + 1; i++)
dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}
int rmq(int l, int r)
{
int k = floor(log((r - l + 1) * 1.0) / log(2.0));
return min(dp[l][k], dp[r - (1 << k) + 1][k]);
}
int lca(int a, int b)
{
if (p[a] > p[b])
swap(a, b);
return f[rmq(p[a], p[b])];
}
/* LCA部分 */
int main()
{
scanf("%d",&n);
scanf("%d",&q);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i < n; i++)
{
int u, v;
scanf("%d",&u);
scanf("%d",&v);
edge[u].push_back(v);
edge[v].push_back(u);
}
Init_hash();
T[0] = bulid(1, m);
dfs(1, 0);
Init_rmq(cnt);
while (q--)
{
int u, v, k;
scanf("%d",&u);
scanf("%d",&v);
scanf("%d",&k);
printf("%d\n", t[query(T[u], T[v], lca(u, v), k)]);
}
return 0;
}