Count on a tree SPOJ - COT (主席樹,LCA)
阿新 • • 發佈:2018-12-14
You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight.
We will ask you to perform the following operation:
- u v k : ask for the kth minimum weight on the path from node u to node v
Input
In the first line there are two integers N
In the second line there are N integers. The ith integer denotes the weight of the ith node.
In the next N-1 lines, each line contains two integers u v, which describes an edge (u, v).
In the next M lines, each line contains three integers u
Output
For each operation, print its result.
Example
Input: 8 5 105 2 9 3 8 5 7 7 1 2 1 3 1 4 3 5 3 6 3 7 4 8
2 5 1
2 5 2
2 5 3
2 5 4
7 8 2
Output: 2
8
9
105
7
給出一棵樹,每個點都自己的權重,然後給出樹上的邊,要求從節點 u 到節點 v 路徑上的第 k 小的權重的大小。
因為權重可能很大,所以需要離散化。
主席樹求區間第 k 小維護的是權值線段樹的字首和,然後通過區間相減得到查詢區間的權值線段樹
所以樹形結構的第 k 小維護的也是權值線段樹的字首和,這裡的字首和表示從第 i 個結點到根的字首和,比如樣例的樹是
那麼我們用主席樹把這八個結點維護成這個樣子
那麼要得到其中兩個點(u,v)之間的樹形結構,就可以看成 TREE(u) + TREE(v) - TREE(lca(u,v))- TREE(fa(lca(u,v))),把查詢看成四棵樹之間的相加相減,然後在求一下lca(u,v)就可以了,這裡我比較懶直接用線上的寫了
1 /* 2 . 3 ';;;;;. 4 '!;;;;;;!;` 5 '!;|&#@|;;;;!: 6 `;;!&####@|;;;;!: 7 .;;;!&@$$%|!;;;;;;!'.`:::::'. 8 '!;;;;;;;;[email protected]###&|;;|%!;!$|;;;;|&&;. 9 :!;;;;[email protected]&%|;;;;;;;;;|!::!!:::;!$%;!$%` '!%&#########@$!:. 10 ;!;;!!;;;;;|$$&@##$;;;::'''''::;;;;|&|%@$|;;;;;;;;;;;;;;;;!$; 11 ;|;;;;;;;;;;;;;;;;;;!%@#####&!:::;!;;;;;;;;;;!&####@%!;;;;$%` 12 `!!;;;;;;;;;;!|%%|!!;::;;|@##%|$|;;;;;;;;;;;;!|%$#####%;;;%&; 13 :@###&!:;;!!||%%%%%|!;;;;;||;;;;||!$&&@@%;;;;;;;|$$##$;;;%@| 14 ;|::;;;;;;;;;;;;|&&$|;;[email protected]&$!;;;;!;;;;;;;;;;;;;;;;!%|;;;%@%. 15 `!!;;;;;;;!!!!;;;;;[email protected]@@&&&&&@$!;!%|;;;;!||!;;;;;!|%%%!;;%@|. 16 %&&$!;;;;;!;;;;;;;;;;;|$&&&&&&&&&@@%!%%;!||!;;;;;;;;;;;;;$##! 17 !%;;;;;;!%!:;;;;;;;;;;!$&&&&&&&&&&@##&%|||;;;!!||!;;;;;;;$&: 18 ':|@###%;:;;;;;;;;;;;;!%$&&&&&&@@$!;;;;;;;!!!;;;;;%&!;;|&%. 19 [email protected]|;;;;;;;;;;;;;;;;;;|%|$&&$%&&|;;;;;;;;;;;;!;;;;;!&@@&' 20 .:%#&!;;;;;;;;;;;;;;!%|$$%%&@%;;;;;;;;;;;;;;;;;;;!&@: 21 .%$;;;;;;;;;;;;;;;;;;|[email protected]&|;;;;;;;;;;;;;;;;;;;;%@%. 22 !&!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;|@#; 23 `%$!;;;;;;;;;;;[email protected]|;;;;;;;;;;;;;;;;;;;;;;;;!%[email protected]#@|. 24 .|@%!;;;;;;;;;!$&%||;;;;;;;;;;;;;;;;;!%[email protected]#|. 25 ;&$!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%#####|. 26 |##$|!;;;;;;::'':;;;;;;;;;;;;;!%[email protected]#@; 27 ;@&|;;;;;;;::'''''':;;;;;;;|$&@###@|` 28 .%##@|;;;;:::''''''''''::;!%&##$' 29 `$##@[email protected]@&|!!;;;:'''''::::;;;;;|&#%. 30 ;&@##&$%!;;;;;;::''''''''::;!|%[email protected]#@&@@: 31 .%@&$$|;;;;;;;;;;:'''':''''::;;;%@#@@#%. 32 :@##@###@$$$$$|;;:'''':;;!!;;;;;;!$#@@#$;` 33 `%@$$|;;;;;;;;:'''''''::;;;;|%$$|!!&###&' 34 |##&%!;;;;;::''''''''''''::;;;;;;;[email protected]&:`!' 35 :;[email protected]$|;;;;;;;::''''''''''':;;;;;;;;!%&@$: [email protected]#$' 36 |##@@&%;;;;;::''''''''':;;;;;;;!%&@#@$%: '%%!%&; 37 |&%!;;;;;;;%$!:''''''':|%!;;;;;;;;|&@%||` '%$|!%&; 38 |@%!;;!!;;;||;:'''''':;%$!;;;;!%%%&#&%$&: .|%;:!&%` 39 [email protected]&%;;;;;;;||;;;:''::;;%$!;;;;;;;|&@%;!$; `%&%!!$&: 40 '$$|;!!!!;;||;;;;;;;;;;%%;;;;;;;|@@|!$##; !$!;:!$&: 41 |#&|;;;;;;!||;;;;;;;;!%|;;;;!$##$;;;;|%' `%$|%%;|&$' 42 |&%!;;;;;;|%;;;;;;;;$$;;;;;;|&&|!|%&&; .:%&$!;;;:[email protected]! 43 `%#&%!!;;;;||;;;;;!$&|;;;!%%%@&!;;;!!;;;|%!;;%@$!%@! 44 !&!;;;;;;;;;||;;%&!;;;;;;;;;%@&!;;!&$;;;|&%;;;%@%` 45 '%|;;;;;;;;!!|$|%&%;;;;;;;;;;|&#&|!!||!!|%[email protected]@|' 46 .!%%&%'`|$; :|$#%|@#&;%#%. 47 */ 48 #include <map> 49 #include <set> 50 #include <list> 51 #include <ctime> 52 #include <cmath> 53 #include <stack> 54 #include <queue> 55 #include <string> 56 #include <vector> 57 #include <cstdio> 58 #include <bitset> 59 #include <cstdlib> 60 #include <cstring> 61 #include <iostream> 62 #include <algorithm> 63 #define lowbit(x) x & (-x) 64 #define mes(a, b) memset(a, b, sizeof a) 65 #define fi first 66 #define se second 67 #define pii pair<int, int> 68 #define INOPEN freopen("in.txt", "r", stdin) 69 #define OUTOPEN freopen("out.txt", "w", stdout) 70 71 typedef unsigned long long int ull; 72 typedef long long int ll; 73 const int maxn = 1e5 + 10; 74 const int maxm = 1e5 + 10; 75 const int mod = 1e9 + 7; 76 const ll INF = 1e18 + 100; 77 const int inf = 0x3f3f3f3f; 78 const double pi = acos(-1.0); 79 const double eps = 1e-8; 80 using namespace std; 81 82 int n, m; 83 int cas, tol, T; 84 85 struct Node { 86 int l, r; 87 int sum; 88 } node[maxn * 50]; 89 int a[maxn]; 90 int rt[maxn]; 91 bool vis[maxn]; 92 int deep[maxn]; 93 int fa[maxn][30]; 94 vector<int> vec[maxn]; 95 vector<int> vv; 96 97 void init() { 98 tol = 0; 99 mes(a, 0); 100 mes(rt, 0); 101 mes(fa, 0); 102 mes(vis, 0); 103 mes(node, 0); 104 mes(deep, 0); 105 vv.clear(); 106 for(int i=1; i<=n; i++) 107 vec[i].clear(); 108 } 109 110 int getid(int x) { 111 return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + 1; 112 } 113 114 void lca_dfs(int u, int f, int d) { 115 deep[u] = d; 116 int len = vec[u].size(); 117 for(int i=0; i<len; i++) { 118 int v = vec[u][i]; 119 if(v == f) continue; 120 if(fa[v][0])continue; 121 fa[v][0] = u; 122 lca_dfs(v, u, d+1); 123 } 124 } 125 126 void lca_update() { 127 for(int j=1; (1<<j)<=n; j++) { 128 for(int i=1; i<=n; i++) { 129 fa[i][j] = fa[fa[i][j-1]][j-1]; 130 } 131 } 132 } 133 134 int lca_query(int u, int v) { 135 if(deep[u] < deep[v]) swap(u, v); 136 int f = deep[u] - deep[v]; 137 for(int i=0; (1<<i)<=f; i++) { 138 if(f & (1<<i)) { 139 u = fa[u][i]; 140 } 141 } 142 if(u != v) { 143 for(int i=(int)log2(n); i>=0; i--) { 144 if(fa[u][i] != fa[v][i]) { 145 u = fa[u][i]; 146 v = fa[v][i]; 147 } 148 } 149 u = fa[u][0]; 150 } 151 return u; 152 } 153 154 void hjt_update(int l, int r, int &x, int y, int pos) { 155 tol++; 156 node[tol] = node[y]; 157 node[tol].sum++; 158 x = tol; 159 if(l == r) return ; 160 int mid = (l + r) >> 1; 161 if(pos <= mid) 162 hjt_update(l, mid, node[x].l, node[y].l, pos); 163 else 164 hjt_update(mid+1, r, node[x].r, node[y].r, pos); 165 } 166 167 void hjt_build(int u, int f) { 168 // printf("%d %d\n", u, f); 169 hjt_update(1, n, rt[u], rt[f], getid(a[u])); 170 vis[u] = true; 171 int len = vec[u].size(); 172 for(int i=0; i<len; i++) { 173 int v = vec[u][i]; 174 if(vis[v]) continue; 175 if(v == f) continue; 176 hjt_build(v, u); 177 } 178 } 179 180 int hjt_query(int l, int r, int x, int y, int lca, int flca, int k) { 181 if(l == r) 182 return l; 183 int mid = (l + r) >> 1; 184 int sum = node[node[x].l].sum + node[node[y].l].sum - node[node[lca].l].sum - node[node[flca].l].sum; 185 if(k <= sum) 186 return hjt_query(l, mid, node[x].l, node[y].l, node[lca].l, node[flca].l, k); 187 else 188 return hjt_query(mid+1, r, node[x].r, node[y].r, node[lca].r, node[flca].r, k-sum); 189 } 190 191 int main() { 192 scanf("%d%d", &n, &m); 193 init(); 194 for(int i=1; i<=n; i++) { 195 scanf("%d", &a[i]); 196 vv.push_back(a[i]); 197 } 198 sort(vv.begin(), vv.end()); 199 vv.erase(unique(vv.begin(), vv.end()), vv.end()); 200 for(int i=1; i<n; i++) { 201 int u, v; 202 scanf("%d%d", &u, &v); 203 vec[u].push_back(v); 204 vec[v].push_back(u); 205 } 206 fa[1][0] = 0; 207 lca_dfs(1, 0, 1); 208 lca_update(); 209 hjt_build(1, 0); 210 while(m--) { 211 int u, v, k; 212 scanf("%d%d%d", &u, &v, &k); 213 int ans = hjt_query(1, n, rt[u], rt[v], rt[lca_query(u, v)], rt[fa[lca_query(u, v)][0]], k); 214 printf("%d\n", vv[ans-1]); 215 } 216 return 0; 217 }View Code