题意:有 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!\n");
75             else{
76                 sort(que+1,que+cnt+1);
77                 printf("%d\n",que[cnt-f+1]);
78             }
79         }
80         else num[a]=b;
81     }
82 }
View Code