hdu3078(lca / RMQ在线)

题目链接: 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\n", 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 }
View Code

 

posted @ 2017-07-20 12:52  geloutingyu  阅读(170)  评论(0编辑  收藏  举报