题意:有 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 }
时间: 2024-10-29 19:06:14