hdu 3078 Network (暴力)+【LCA】

时间:2022-06-14 15:10:37

<题目链接>

题目大意:
给定一颗带点权的树,进行两种操作,k=0,更改某一点的点权,k!=0,输出a~b路径之间权值第k大的点的点权。

解题分析:
先通过RMQ的初始化,预处理pre[]数组,并且求出a和b的LCA。然后利用LCA将a、b路径上所有点的点权全部存储起来,将其排序,就可得到a、b路径上权值第k大的点权。具体操作为:利用pre[]数组,从a到LCA的所有点权全部相加,然后再将从b到LCA的所有点权相加,就可以得到a、b路径上所有点的点权。下面用的是LCA转RMQ的方法求解。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std; const int maxn = 8e4+;
struct Edge{
int to,next;
}edge[maxn<<];
int n,q,cnt,num,tot,pre[maxn],val[maxn],fa[maxn];
int st[maxn<<][],ver[maxn<<],dep[maxn<<],first[maxn],path[maxn]; bool cmp(int a,int b){ return a > b;}
int Min(int l,int r){
return dep[l]<dep[r]?l:r;
}
void addedge(int u,int v){
edge[num].to = v,edge[num].next = pre[u];
pre[u] = num++;
}
void dfs(int u,int deep){
ver[++cnt] = u; first[u] = cnt; dep[cnt] = deep;
for(int i = pre[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if(fa[u] == v) continue;
fa[v] = u;
dfs(v,deep+);
ver[++cnt] = u; dep[cnt] = deep;
}
}
void RMQ_init(){
for(int i = ; i <= cnt; i++)
st[i][] = i;
for(int j = ; ( << j) <= cnt; j++)
for(int i = ; i + ( << j) < cnt; i++)
st[i][j] = Min(st[i][j-],st[i+(<<(j-))][j-]);
}
int findLCA(int l,int r){
int k = (int)(log(r - l + 1.0) / log(2.0));
return ver[Min(st[l][k],st[r-(<<k)+][k])];
}
//以上是LCA转RMQ的模板
int main(){
int k,a,b;
while(scanf("%d%d",&n,&q)!=EOF){
cnt = num = ;
memset(pre,-,sizeof(pre));
for(int i = ; i <= n; i++)
scanf("%d",&val[i]);
for(int i = ; i < n; i++){
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
dfs(,);
RMQ_init();
while(q--){
scanf("%d%d%d",&k,&a,&b);
if(k == )val[a] = b;
else{
int x = first[a], y = first[b];
if(x > y) swap(x,y);
int lca = findLCA(x,y); //得到最近公共祖先
tot = ;
while(a != lca){ //将a到最近公共祖先的路劲上所有的点权放入path数组
path[++tot] = val[a];
a = fa[a];
}
while(b != lca){ //将a到最近公共祖先的路劲上所有的点权放入path数组
path[++tot] = val[b];
b = fa[b];
}
path[++tot] = val[lca]; //再加上lca的点权
if(k > tot) printf("invalid request!\n");
else{
sort(path+,path++tot,cmp); //将a->b路劲上所有点权排序,然后就可以得到第k大的点权
printf("%d\n",path[k]);
}
}
}
}
return ;
}

2018-10-23