题意:有 n 点的一颗树,每个节点有格子的权值,现在有两种操作,修改一个点的权值,或者求两点之间的路径上的第 k 大的权值。
其实看到这个题,就在 YY 各种做法,询问后得到貌似可能是关于主席树、树链剖分等高端数据结构做的,但事实上,大概是出题人也并不想出难题,只是为了练练手所以……直接把每个问题路径上的点权保存在数组中 sort 一下就行了。然后树上路径就果断是LCA了,不过这里LCA也就不用倍增了,直接一步一步向上爬然后顺便加数组就行了。
1 #include<stdio.h>
2 #include<string.h>
3 #include<algorithm>
4 using namespace std;
5
6 const int maxn=8e4+5;
7 const int maxm=maxn*2;
8
9 int fa[maxn],dep[maxn];
10 int head[maxn],point[maxm],nxt[maxm],size;
11 int n,num[maxn],que[maxn],cnt;
12
13 void init(){
14 size=0;
15 memset(head,-1,sizeof(head));
16 }
17
18 void add(int a,int b){
19 point[size]=b;
20 nxt[size]=head[a];
21 head[a]=size++;
22 point[size]=a;
23 nxt[size]=head[b];
24 head[b]=size++;
25 }
26
27 void Dfs(int s,int pre){
28 fa[s]=pre;
29 dep[s]=dep[pre]+1;
30 for(int i=head[s];~i;i=nxt[i]){
31 int j=point[i];
32 if(j==pre)continue;
33 Dfs(j,s);
34 }
35 }
36
37 void Pre(){
38 dep[1]=0;
39 Dfs(1,-1);
40 }
41
42 void Lca(int u,int v){
43 cnt=0;
44 if(dep[u]>dep[v])swap(u,v);
45 while(dep[u]<dep[v]){
46 que[++cnt]=num[v];
47 v=fa[v];
48 }
49 while(u!=v){
50 que[++cnt]=num[u];
51 u=fa[u];
52 que[++cnt]=num[v];
53 v=fa[v];
54 }
55 que[++cnt]=num[u];
56 }
57
58 int main(){
59 int m;
60 scanf("%d%d",&n,&m);
61 init();
62 for(int i=1;i<=n;++i)scanf("%d",&num[i]);
63 for(int i=1;i<n;++i){
64 int a,b;
65 scanf("%d%d",&a,&b);
66 add(a,b);
67 }
68 Pre();
69 while(m--){
70 int f,a,b;
71 scanf("%d%d%d",&f,&a,&b);
72 if(f){
73 Lca(a,b);
74 if(cnt<f)printf("invalid request!
");
75 else{
76 sort(que+1,que+cnt+1);
77 printf("%d
",que[cnt-f+1]);
78 }
79 }
80 else num[a]=b;
81 }
82 }