bzoj 4336[BJOI2015]骑士的旅行 - 树链剖分 + mulitiset
4336: BJOI2015 骑士的旅行
Time Limit: 20 Sec Memory Limit: 512 MBDescription
在一片古老的土地上,有一个繁荣的文明。
这片大地几乎被森林覆盖,有N座城坐落其中。巧合的是,这N座城由恰好N-1条双向道路连接起来,使得任意两座城都是连通的。
也就是说,这些城形成了树的结构,任意两座城之间有且仅有一条简单路径。
在这个文明中,骑士是尤其受到尊崇的职业。任何一名骑士,都是其家族乃至家乡的荣耀。Henry从小就渴望成为一名能守护家乡、驱逐敌人的骑士。勤奋训练许多年后,Henry终于满18岁了。他决定离开家乡,向那些成名已久的骑士们发起挑战!根据Henry的调查,大陆上一共有M名受封骑士,不妨编号为1到M。
第i个骑士居住在城Pi,武力值为Fi。Henry计划进行若干次旅行,每次从某座城出发沿着唯一的简单路径前往另一座城,
同时会挑战路线上武力值最高的K个骑士(Henry的体力有限,为了提高水平,当然要挑战最强的骑士)。如果路线上的骑士不足K人,Henry会挑战遇到的所有人。
每次旅行前,可能会有某些骑士的武力值或定居地发生变化,Henry自然会打听消息,并对计划做出调整。
为了在每次旅行时做好充分准备,Henry希望你能帮忙在每次旅行前计算出这条路线上他将挑战哪些对手。
Input
第一行,一个整数N,表示有N座城,编号为1~N。
接下来N-1行,每行两个整数Ui和Vi,表示城Ui和城Vi之间有一条道路相连。
第N+1行,一个整数M,表示有M个骑士。
接下来M行,每行两个整数Fi和Pi。按顺序依次表示编号为1~M的每名骑士的武
力值和居住地。
第N+M+2行,两个整数Q,K,分别表示操作次数和每次旅行挑战的骑士数目上限。
接下来Q行,每行三个整数Ti,Xi,Yi。Ti取值范围为{1,2,3},表示操作类型。
一共有以下三种类型的操作:
Ti=1时表示一次旅行,Henry将从城Xi出发前往城市Yi;
Ti=2时表示编号为Xi的骑士的居住地搬到城Yi;
Ti=3时表示编号为Xi的骑士的武力值修正为Yi。
Output
输出若干行,依次为每个旅行的答案。
对每个Ti=1的询问,输出一行,按从大到小的顺序输出Henry在这次旅行中挑战的
所有骑士的武力值。如果路线上没有骑士,输出一行,为一个整数-1。
Sample Input
5
1 2
1 3
2 4
2 5
4
10 1
6 1
14 5
7 3
5 3
1 2 3
1 5 3
1 4 4
2 1 4
1 2 3
1 2
1 3
2 4
2 5
4
10 1
6 1
14 5
7 3
5 3
1 2 3
1 5 3
1 4 4
2 1 4
1 2 3
Sample Output
10 7 6
14 10 7
-1
7 6
14 10 7
-1
7 6
HINT
100%的数据中,1 ≤ N, M ≤ 40,000,1 ≤ Ui, Vi, Pi ≤ N,1 ≤ Q ≤ 80,000, 1 ≤ K ≤
20,旅行次数不超过 40,000 次,武力值为不超过1,000的正整数。
对于这类树上问题,可以考虑树链剖分解决
重点是如何维护前k大个
对于一个单点,可以用muiliset 直接按顺序存储所有的人
这样向上合并的时候就用归并的思想很简单就解决了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <set> 6 #define LL long long 7 8 using namespace std; 9 10 const int MAXN = 5e4 + 10; 11 12 int T; 13 int x, y; 14 multiset<int> city[MAXN]; 15 int ans[30]; 16 int N, M; 17 int head[MAXN]; 18 int m[MAXN]; 19 int cnt = 0; 20 int vis[MAXN]; 21 int dfn[MAXN], top[MAXN], fa[MAXN]; 22 int size[MAXN], son[MAXN]; 23 int deep[MAXN]; 24 int Q, K; 25 26 struct edge { 27 int v; 28 int next; 29 } g[MAXN * 2]; 30 31 struct segment { 32 int l, r; 33 int big[30]; 34 } seg[MAXN * 20]; 35 36 struct knight { 37 int force, loc; 38 } kt[MAXN]; 39 40 void addedge(int u, int v) 41 { 42 g[++cnt].v = v; 43 g[cnt].next = head[u]; 44 head[u] = cnt; 45 } 46 47 inline LL read() 48 { 49 LL x = 0, w = 1; char ch = 0; 50 while(ch < '0' || ch > '9') { 51 if(ch == '-') { 52 w = -1; 53 } 54 ch = getchar(); 55 } 56 while(ch >= '0' && ch <= '9') { 57 x = x * 10 + ch - '0'; 58 ch = getchar(); 59 } 60 return x * w; 61 } 62 63 void pushup(int x) 64 { 65 int l1 = 1, l2 = 1; 66 for(int i = 1; i <= K; i++) { 67 if(seg[x * 2].big[l1] >= seg[x * 2 + 1].big[l2]) { 68 seg[x].big[i] = seg[x * 2].big[l1++]; 69 } else { 70 seg[x].big[i] = seg[x * 2 + 1].big[l2++]; 71 } 72 } 73 } 74 75 void merge(int x) 76 { 77 int temp[30]; 78 int l1 = 1, l2 = 1; 79 for(int i = 1; i <= K; i++) { 80 temp[i] = ans[i]; 81 } 82 for(int i = 1; i <= K; i++) { 83 if(temp[l1] >= seg[x].big[l2]) { 84 ans[i] = temp[l1++]; 85 } else { 86 ans[i] = seg[x].big[l2++]; 87 } 88 } 89 } 90 91 void dfs1(int x) 92 { 93 deep[x] = deep[fa[x]] + 1; 94 size[x] = 1; 95 vis[x] = 1; 96 for(int j = head[x]; j; j = g[j].next) { 97 int to = g[j].v; 98 if(!vis[to]) { 99 fa[to] = x; 100 dfs1(to); 101 size[x] += size[to]; 102 if(size[to] > size[son[x]]) { 103 son[x] = to; 104 } 105 } 106 } 107 } 108 109 void dfs2(int x, int k) 110 { 111 top[x] = k; 112 dfn[x] = ++cnt; 113 m[cnt] = x; 114 if(son[x]) { 115 dfs2(son[x], k); 116 } 117 for(int j = head[x]; j; j = g[j].next) { 118 int to = g[j].v; 119 if(!dfn[to]) { 120 dfs2(to, to); 121 } 122 } 123 } 124 125 void update(int u, int l, int r, int root, int k) 126 { 127 if(l == r) { 128 city[m[l]].insert(k); 129 multiset<int>::iterator t; 130 int i = 1; 131 t = city[m[l]].end(); 132 t--; 133 for(; i <= K; i++, t--) { 134 seg[root].big[i] = *t; 135 if(t == city[m[l]].begin()) { 136 i++; 137 for(; i <= K; i++) { 138 seg[root].big[i] = 0; 139 } 140 break; 141 } 142 } 143 return; 144 } 145 int mid = (l + r) >> 1; 146 if(u <= mid) { 147 update(u, l, mid, root * 2, k); 148 } else { 149 update(u, mid + 1, r, root * 2 + 1, k); 150 } 151 pushup(root); 152 } 153 154 void del(int u, int l, int r, int root, int k) 155 { 156 if(l == r) { 157 multiset<int> :: iterator t; 158 t = city[m[l]].find(k); 159 city[m[l]].erase(t); 160 int i = 1; 161 t = city[m[l]].end(); 162 if(city[m[l]].empty()) { 163 for(int i = 1; i <= K; i++) { 164 seg[root].big[i] = 0; 165 } 166 return; 167 } 168 t--; 169 for(; i <= K; i++, t--) { 170 seg[root].big[i] = *t; 171 if(t == city[m[l]].begin()) { 172 i++; 173 for(;i <= K; i++) { 174 seg[root].big[i] = 0; 175 } 176 break; 177 } 178 } 179 return; 180 } 181 int mid = (l + r) >> 1; 182 if(u <= mid) { 183 del(u, l, mid, root * 2, k); 184 } else { 185 del(u, mid + 1, r, root * 2 + 1, k); 186 } 187 pushup(root); 188 } 189 190 void build() 191 { 192 dfs1(1); 193 cnt = 0; 194 dfs2(1, 1); 195 } 196 197 void query(int ql, int qr, int l, int r, int root) 198 { 199 if(l >= ql && r <= qr) { 200 merge(root); 201 return; 202 } 203 int mid = (l + r) >> 1; 204 if(mid >= ql) { 205 query(ql, qr, l, mid, root * 2); 206 } 207 if(mid < qr) { 208 query(ql, qr, mid + 1, r, root * 2 + 1); 209 } 210 } 211 212 int LCA(int x, int y) 213 { 214 int fx = top[x], fy = top[y]; 215 while(fx != fy) { 216 if(deep[fx] >= deep[fy]) { 217 query(dfn[fx], dfn[x], 1, N, 1); 218 x = fa[fx]; 219 fx = top[x]; 220 } else { 221 query(dfn[fy], dfn[y], 1, N, 1); 222 y = fa[fy]; 223 fy = top[y]; 224 } 225 } 226 if(deep[x] >= deep[y]) { 227 query(dfn[y], dfn[x], 1, N, 1); 228 return y; 229 } else { 230 query(dfn[x], dfn[y], 1, N, 1); 231 return x; 232 } 233 } 234 235 int main() 236 { 237 //freopen("knight10.in", "r", stdin); 238 //freopen("knight.out", "w", stdout); 239 N = read(); 240 for(int i = 1; i < N; i++) { 241 int u = read(), v = read(); 242 addedge(u, v); 243 addedge(v, u); 244 } 245 build(); 246 M = read(); 247 for(int i = 1; i <= M; i++) { 248 kt[i].force = read(), kt[i].loc = read(); 249 } 250 Q = read(), K = read(); 251 for(int i = 1; i <= M; i++) { 252 update(dfn[kt[i].loc], 1, N, 1, kt[i].force); 253 } 254 int tot = 1; 255 while(Q--) { 256 /*cout<<tot++<<endl; 257 multiset<int> ::iterator t; 258 t = city[4527].begin(); 259 for(; t != city[4527].end(); t++) { 260 cout<<*t<<" "; 261 } 262 cout<<endl;*/ 263 T = read(); 264 x = read(), y = read(); 265 //cout<<T<<" "<<x<<" "<<y<<endl; 266 if(T == 1) { 267 for(int i = 1; i <= K; i++) { 268 ans[i] = 0; 269 } 270 /*if(x == 1 && y == 2){ 271 multiset<int> ::iterator t; 272 t = city[x].begin(); 273 for(; t != city[x].end(); t++) { 274 cout<<*t<<" "; 275 } 276 cout<<endl; 277 278 }*/ 279 LCA(x, y); 280 /*for(int i = 1; i <= N; i++) { 281 for(int j = 1; j <= 20; j++) { 282 ans[j] = 0; 283 } 284 query(dfn[i], dfn[i], 1, N, 1); 285 for(int j = 1; j <= 3; j++) { 286 cout<<ans[j]<<" "; 287 } 288 cout<<endl<<endl; 289 }*/ 290 for(int i = 1; i <= K; i++) { 291 if(ans[i] == 0) { 292 if(i == 1) { 293 printf("-1"); 294 } 295 break; 296 } 297 printf("%d ", ans[i]); 298 } 299 printf("\n"); 300 } else if(T == 2) { 301 /*if(x == 720 && y == 6713) { 302 cout<<dfn[kt[x].loc] <<" "<<kt[x].force<<" "<<kt[x].loc<<endl; 303 multiset<int> ::iterator t; 304 t = city[kt[x].loc].begin(); 305 for(; t != city[kt[x].loc].end(); t++) { 306 cout<<*t<<" "; 307 } 308 cout<<endl; 309 return 0; 310 }*/ 311 del(dfn[kt[x].loc], 1, N, 1, kt[x].force); 312 kt[x].loc = y; 313 update(dfn[kt[x].loc], 1, N, 1, kt[x].force); 314 } else { 315 del(dfn[kt[x].loc], 1, N, 1, kt[x].force); 316 kt[x].force = y; 317 update(dfn[kt[x].loc], 1, N, 1, kt[x].force); 318 } 319 } 320 } 321 322 323 /* 324 5 325 326 1 2 327 328 1 3 329 330 2 4 331 332 2 5 333 334 4 335 336 10 1 337 338 6 1 339 340 14 5 341 342 7 3 343 344 5 3 345 346 1 2 3 347 348 1 5 3 349 350 1 4 4 351 352 2 1 4 353 354 1 2 3 355 356 */