HDU3078 Network (倍增LCA算法求树链)

题意:

一棵无向树,输入点数和操作数,下面一行n个值代表每个点的权。下面n-1行是树边 操作分为 0 x w ,表示把点x的权改为w; k a b , 求出,从a到b的路径中,第k大的点权

题解:

对于每组询问,先求出两点的LCA,再从两点分别向LCA遍历,保存路径上所有的点权,排序输出第K大即可~

#include<cstdio>
#include<algorithm>
#include<cstring> 
#include<vector>
using namespace std;
const int maxn=1e5+10;
int N,M,Q;
int t[maxn];
int cnt=0;
int head[maxn];
int tol;
struct node {
    int u;
    int v;
    int w;
    int next;
}edge[maxn*2];
void addedge (int u,int v) {
    edge[tol].u=u;
    edge[tol].v=v;
    edge[tol].next=head[u];
    head[u]=tol++;
}
int weight[maxn];
int d[maxn];
int h[maxn];
int father[20][maxn];
void dfs (int x) {
    for (int i=head[x];i!=-1;i=edge[i].next) {
        int v=edge[i].v;
        if (v==father[0][x]) continue;
        father[0][v]=x;
        h[v]=h[x]+1;
        dfs(v);
    }
}
int lca (int x,int y) {
    if (h[x]<h[y]) swap(x,y);
    for (int i=17;i>=0;i--) 
        if (h[x]-h[y]>>i) x=father[i][x];
    if (x==y) return x;
    for (int i=17;i>=0;i--) {
        if (father[i][x]!=father[i][y]) {
            x=father[i][x];
            y=father[i][y];
        }
    }
    return father[0][x];
}
int main () {
    scanf("%d%d",&N,&Q);
    memset(head,-1,sizeof(head));
    for (int i=1;i<=N;i++) 
        scanf("%d",&weight[i]);
    for (int i=0;i<N-1;i++) {
        int u,v;
        scanf("%d%d",&u,&v);
        addedge(u,v);
        addedge(v,u);
    }
    dfs(1);
    for (int i=1;i<=17;i++) 
        for (int j=1;j<=N;j++)
            father[i][j]=father[i-1][father[i-1][j]];
    for (int i=0;i<Q;i++) {
        int k,x,y;
        scanf("%d%d%d",&k,&x,&y);
        if (k==0) weight[x]=y;
        else {
            int r=lca(x,y);
            cnt=0;
            while (x!=r) {
                t[cnt++]=weight[x];
                x=father[0][x];
            }
            while (y!=r) {
                t[cnt++]=weight[y];
                y=father[0][y];
            }
            t[cnt++]=weight[r];
            sort(t,t+cnt);
            if (cnt<k) {
                printf("invalid request!
");
                continue;
            } 
            printf("%d
",t[cnt-k]);
        }
    }
}
原文地址:https://www.cnblogs.com/zhanglichen/p/12527160.html