题意是给你一棵树,树上的节点有权值,输入a,b,c,查询b到c路径中排第a的值,如果a是0,则是修改点b的值为c.这题只要打一个在线的LCA然后每次查询,把路径上的值记录在数组中,排序并输出就好。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
#include <math.h>
#define maxn 80005
#define maxm 160005
#define inf (1e8 + 7)
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
int heads[maxn], num[maxn], sizes, id[maxm], dep[maxm], vis[maxn], vi[maxn], pre[maxn], dp[maxm][25], n, m, flag, root, pre2[maxn];
bool vis2[maxn];
struct edge
{
int v, next;
}eg[maxm];
bool cmp(int a, int b)
{
return a > b;
}
void inits()
{
mem(vis, 0);
mem(vis2, 0);
mem(heads, -1);
mem(vi, 0);
sizes = 0;
flag = 1;
return;
}
void add(int u, int v)
{
eg[sizes].v = v;
eg[sizes].next = heads[u];
heads[u] = sizes++;
return;
}
void dfs(int u, int d)
{
id[flag] = u;
dep[flag] = d;
flag++;
for(int i = heads[u];i != -1;i = eg[i].next)
{
int v = eg[i].v;
if(!vis[v])
{
pre2[v] = u;
vis[v] = flag;
dfs(v, d + 1);
id[flag] = u;
dep[flag] = d;
flag++;
}
}
}
int pr(int a)
{
if(a == pre[a])
return a;
return pre[a] = pr(pre[a]);
}
void con(int u, int v)
{
int a = pr(u);
int b = pr(v);
if(a < b)
pre[b] = a;
else if(a > b)
pre[a] = b;
return;
}
void rmq_dp(int nn)
{
for(int i = 1;i <= nn;i++)
dp[i][0] = i;
for(int j = 1;(1 << j) <= nn;j++)
{
int k = (1 << (j - 1));
for(int i = 1;i + k < nn;i++)
{
if(dep[dp[i][j - 1]] <= dep[dp[i + k][j - 1]])
dp[i][j] = dp[i][j - 1];
else
dp[i][j] = dp[i + k][j - 1];
}
}
return;
}
int rmq(int a, int b)
{
int dis = b - a + 1;
int k = log((double)dis) / log(2.0);
if(dep[dp[a][k]] <= dep[dp[b - (1 << k) + 1][k]])
return dp[a][k];
else
return dp[b - (1 << k) + 1][k];
}
int lca(int a, int b)
{
int u = vis[a];
int v = vis[b];
if(u <= v)
return id[rmq(u, v)];
else
return id[rmq(v, u)];
}
int main()
{
root = 0;
int a, b, c;
while(~scanf("%d%d", &n, &m))
{
inits();
for(int i = 1;i <= n;i++)
scanf("%d", &vi[i]), pre[i] = i, pre2[i];
for(int i = 1;i < n;i++)
{
scanf("%d%d", &a, &b);
add(a, b);
add(b, a);
con(a, b);
}
for(int i = 1;i <= n;i++)
pr(i);
for(int i = 1;i <= n;i++)
vis2[pre[i]] = 1;
for(int i = 1;i <= n;i++)
{
if(vis2[i])
add(root, i);
}
vis[root] = 1;
dfs(root, 0);
rmq_dp(flag - 1);
for(int i = 0;i < m;i++)
{
scanf("%d%d%d", &a, &b, &c);
if(!a)
vi[b] = c;
else
{
int tmp = lca(b, c);
int u = b;
int nn = 0;
while(u != tmp)
{
num[nn++] = vi[u];
u = pre2[u];
}
u = c;
while(u != tmp)
{
num[nn++] = vi[u];
u = pre2[u];
}
num[nn++] = vi[tmp];
if(a > nn)
printf("invalid request!\n");
else
{
sort(num, num + nn, cmp);
printf("%d\n", num[a - 1]);
}
}
}
}
return 0;
}