题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078
题意: 给出一棵 n 个点的带点权值的树, 接下来有 q 组形如 k, x, y 的输入, 若 k == 0 则将 x 点的权值替换成 y, 否则输出 x 到 y 之间顶点地 k 大的权值.
思路: 用一个数组 val 记录一下每个顶点的权值, 对于k == 0, 直接令 val[x] = y 即可 .
对于询问, 可以先求出 lca, 再记录一下路径上的顶点的权值, sort 一下, 输出第 k 大的即可.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <math.h> 4 #include <string.h> 5 #include <algorithm> 6 #include <vector> 7 using namespace std; 8 9 const int MAXN = 8e4 + 10; 10 vector<int> vt[MAXN]; 11 int dp[MAXN << 1][30]; 12 int first[MAXN], ver[MAXN << 1], deep[MAXN << 1]; 13 int pre[MAXN], val[MAXN], yy[MAXN], ip = 0, indx = 0; 14 15 bool cmp(int x, int y){ 16 return x > y; 17 } 18 19 void dfs(int u, int h, int fa){ 20 pre[u] = fa; 21 ver[++indx] = u; 22 deep[indx] = h; 23 first[u] = indx; 24 for(int i = 0; i < vt[u].size(); i++){ 25 int v = vt[u][i]; 26 if(v != fa){ 27 dfs(v, h + 1, u); 28 ver[++indx] = u; 29 deep[indx] = h; 30 } 31 } 32 } 33 34 void ST(int n){ 35 for(int i = 1; i <= n; i++){ 36 dp[i][0] = i; 37 } 38 for(int j = 1; (1 << j) <= n; j++){ 39 for(int i = 1; i + (1 << j) - 1 <= n; i++){ 40 int x = dp[i][j - 1], y = dp[i + (1 << (j - 1))][j -1]; 41 dp[i][j] = deep[x] < deep[y] ? x : y; 42 } 43 } 44 } 45 46 int RMQ(int l, int r){ 47 int len = log2(r - l + 1); 48 int x = dp[l][len], y = dp[r - (1 << len) + 1][len]; 49 return deep[x] < deep[y] ? x : y; 50 } 51 52 int LCA(int x, int y){ 53 int l = first[x]; 54 int r = first[y]; 55 if(l > r) swap(l, r); 56 int pos = RMQ(l, r); 57 return ver[pos]; 58 } 59 60 void path(int x, int root, int &pos){ 61 while(x != root && x != -1){ 62 yy[pos++] = val[x]; 63 x = pre[x]; 64 } 65 } 66 67 void solve(int x, int y, int k){ 68 int pos = 0, lca = LCA(x, y); 69 path(x, lca, pos); 70 path(y, lca, pos); 71 yy[pos++] = val[lca]; 72 if(pos < k) puts("invalid request!"); 73 else{ 74 sort(yy, yy + pos, cmp);//注意是从大到小的第 k 大!!!!!!!!! 75 printf("%d ", yy[k - 1]); 76 } 77 } 78 79 int main(void){ 80 int n, q, x, y, op; 81 scanf("%d%d", &n, &q); 82 for(int i = 1; i <= n; i++){ 83 scanf("%d", &val[i]); 84 } 85 for(int i = 1; i < n; i++){ 86 scanf("%d%d", &x, &y); 87 vt[x].push_back(y); 88 vt[y].push_back(x); 89 } 90 dfs(1, 1, -1); 91 ST(indx); 92 while(q--){ 93 scanf("%d%d%d", &op, &x, &y); 94 if(!op) val[x] = y; 95 else solve(x, y, op); 96 } 97 return 0; 98 }