1 一、区间划分 2 //区间划分+持久化并查集:区间连通情况统计。 3 inline bool comp(Ask x, Ask y){return x.km == y.km ? x.l > y.l : x.km > y.km ; } 4 inline void init()//把编号相同的放一起,l从大到小;{ 5 int i ; 6 ms = sqrt(1.0*n) ; //大小 7 mg = n/ms ; //块数 8 mg = mg*ms == n ? mg : mg + 1 ; 9 for(i = 1 ; i <= n ; i ++) e[i].clear() ; 10 } 11 /*********************持久化并查集**********************************/ 12 void solve()//区间划分{ 13 int i = 1, j, k, l, r ; 14 sort(ask+1, ask+1+q, comp) ; 15 while(i <= q) //询问 16 { 17 k = ask[i].km ; 18 for(; i <= q && ask[i].km == k && ask[i].l > (k-1)*ms ; i ++) //处理区间小于ms的询问 19 ans[ask[i].no] = bfAnswer(i) ; 20 if(i > q || ask[i].km != k ) //全部为小区间 21 continue ; 22 r = (k-1)*ms ; //最右端 23 initSet(lp, 1, r) ; //初始化并查集 ; 24 for(j = 1 ; j <= r ; j ++) vis[j] = 0 ; 25 while(i <= q && ask[i].km == k ) //求解第k块的所有大询问; 26 { 27 l = ask[i].l ; 28 for(j = r ; j >= l ; j -- ) //加入顶点j 29 addVex(lp, j, (k-1)*ms) ; 30 r = j ; 31 for(; i <= q && ask[i].km == k && ask[i].l == l ; i ++) 32 //计算所有左端等于l的区间; 33 { 34 ans[ask[i].no] = unionRSet(ask[i].no, l, (k-1)*ms+1, ask[i].r ) ; //右端暴力合并 ; 35 } 36 } 37 } 38 } 39 二、2B树:动态区间比x小的数的个数。 40 void DT_insert(int rt, int x, int s ){ 41 int i = DN, j, p ; 42 getBinary(x) ; 43 j = dig[i--] ; 44 if(root[rt].next[j] == -1) 45 { 46 root[rt].next[j] = ++ tot ; 47 pool[tot].set() ; 48 } 49 if(!j) root[rt].sum += s ; 50 p = root[rt].next[j] ; 51 while(i) 52 { 53 j = dig[i--] ; 54 if(pool[p].next[j] == -1) 55 { 56 pool[p].next[j] = ++ tot ; 57 pool[tot].set() ; 58 } 59 if(!j)pool[p].sum += s ; 60 p = pool[p].next[j] ; 61 } 62 } 63 int DT_count(int rt, int x){ 64 int i = DN, j, p, ans = 0 ; 65 getBinary(x) ; 66 j = dig[i--] ; 67 if(j) ans += root[rt].sum ; 68 if(root[rt].next[j] == -1) return ans ; 69 p = root[rt].next[j] ; 70 while(i) 71 { 72 j = dig[i--] ; 73 if(j) ans += pool[p].sum ; 74 if(pool[p].next[j] == -1) return ans ; 75 p = pool[p].next[j] ; 76 } 77 return ans ; 78 } 79 void DT_build(){ 80 int i, k ; 81 size = sqrt(double(n)) ; 82 mg = n/size ; 83 mg = mg*size == n ? mg : mg+1 ; 84 for(i = 1 ; i <= mg ; i ++) root[i].set() ; 85 for(i = 1 ; i <= n ; i ++) 86 { 87 k = (i-1)/size + 1 ; 88 DT_insert(k, ar[i], 1) ; 89 } 90 bs = 10*size ; 91 bmg = n/bs ; 92 bmg = bmg*bs == n ? bmg : bmg + 1 ; 93 for(i = 1 ; i <= bmg+1 ; i ++) root[MAXS+i].set() ; 94 for(i = 1 ; i <= n ; i ++) 95 { 96 k = (i-1)/bs + 1 ; 97 DT_insert(MAXS+k, ar[i], 1) ; 98 } 99 } 100 int DT_query(int l, int r, int x){ 101 int i, k, ans = 0, bk ; 102 k = (l-1)/size + 1 ; 103 k = size*(k-1)+1 == l ? k : k + 1 ; //前 104 for(i = l ; i <= r && i < (k-1)*size+1 ; i ++) ans = ar[i] < x ? ans+1 : ans ; 105 for(; i <= r && r-i+1 >= size && (k%10 != 1) ; i += size, k ++) //小块 106 ans += DT_count(k, x) ; 107 for(bk = (k-1)/10+1 ; i <= r && r-i+1 >= bs ; i += bs, bk ++, k += 10) 108 ans += DT_count(MAXS+bk, x) ;//大块 109 for(; i <= r && r-i+1 >= size ; i += size, k ++) //小块 110 ans += DT_count(k, x) ; 111 for(; i <= r ; i ++) ans = ar[i] < x ? ans+1 : ans ; 112 return ans ; 113 } 114 三、树链剖分 115 1. 树上区间[u, v] 异或 x 的最大值 116 // 持久化2B树 + 树链剖分(区间可直接合并) 117 inline void insert(int rt, int x) ; //建一颗空树 118 inline void addNumber(int pre, int &rt, int id, int x){//持久化 119 int i = SD, p ; 120 bool j ; 121 rt = ++dcnt ; p = rt ; 122 while(i >= 0 ) 123 { 124 pool[p] = pool[pre] ; 125 j = x&(1<<i) ; 126 pool[p].mx[j] = id ; 127 pool[p].next[j] = ++dcnt ; 128 p = dcnt ; 129 pre = pool[pre].next[j] ; 130 i -- ; 131 } 132 pool[p].x = x ; 133 } 134 inline int DTcount(int rt,int l,int x)//计算前缀树[1,r]中下标>=l的与x的最大异或值 135 /*******c******************树链剖分*************************/ 136 void DFS(int u){ 137 int i, to ; 138 siz[u] = 1 ; son[u] = 0 ; 139 for(i = head[u] ; i != -1 ; i = e[i].next ) 140 { 141 to = e[i].to ; 142 if(to != fa[u]) 143 { 144 fa[to] = u ; 145 dep[to] = dep[u] + 1 ; 146 DFS(to) ; 147 if(siz[son[u]] < siz[to]) son[u] = to ; 148 siz[u] += siz[to] ; 149 } 150 } 151 } 152 void cutLink(int u, int tp){ 153 w[u] = ++cnt ; 154 top[u] = tp ; 155 if(son[u]) cutLink(son[u], tp) ; 156 for(int i = head[u] ; i != -1 ; i = e[i].next) 157 { 158 int to = e[i].to ; 159 if(to != fa[u] && to != son[u]) cutLink(to, to) ; 160 } 161 } 162 void buildTree(){ 163 dep[1] = 1 ; 164 cnt = fa[1] = siz[0] = 0 ; 165 DFS(1) ; 166 cutLink(1, 1) ; 167 int i ; 168 for(i = 1 ; i <= n ; i ++) val[w[i]] = ar[i] ; 169 pool[0].set() ; 170 dcnt = T[0] = 0 ; 171 for(i = 1 ; i <= cnt ; i ++) insert(T[0], val[i]) ; 172 for(i = 1 ; i <= cnt ; i ++) addNumber(T[i-1], T[i], i, val[i]) ;//持久化思 173 } 174 int getAns(int u, int v, int x){ 175 int ans = 0, tu = top[u], tv = top[v], tmp ; 176 if(u == v) return DTcount(T[w[u]], w[v], x) ; ; 177 while(tu != tv) //如果不在同一条链上 178 { 179 if(dep[tu] < dep[tv]) {swap(tu, tv) ; swap(u, v) ; } 180 tmp = DTcount(T[w[u]], w[tu], x ) ; //查询从u到tu的父亲的最大值 181 ans = max(ans, tmp) ; 182 u = fa[tu] ; 183 tu = top[u] ; 184 } 185 if(dep[u] < dep[v]) swap(u, v) ; 186 tmp = DTcount(T[w[u]], w[v], x) ; 187 return max(ans, tmp) ; 188 } 189 2. BFS实现建树 190 int leaf[MAXN], ns[MAXN], ct[MAXN]; 191 void BFS(int rt){ 192 int i, h = 0, t = 0, l = 0, r = 0 ; 193 int u, to ; 194 que[t++] = rt ; 195 for(i = 1 ; i <= n ; i ++) 196 { 197 siz[i] = 1 ; 198 ct[i] = ns[i] = son[i] = 0 ; 199 } 200 while (h < t) // calculate the dep. 201 { 202 u = que[h++] ; 203 for(i = head[u] ; i != -1 ; i = e[i].next) 204 { 205 to = e[i].to ; 206 if(to != fa[u]) 207 { 208 ns[u] ++ ; 209 fa[to] = u ; 210 dep[to] = dep[u] + 1 ; 211 que[t++] = to ; 212 } 213 } 214 } 215 for(i = 1 ; i <= n ; i ++) if(ns[i] == 0) leaf[r++] = i ; 216 while(l < r) 217 { 218 to = leaf[l++] ; 219 u = fa[to] ; 220 siz[u] += siz[to] ; ct[u] ++ ; 221 if(ct[u] == ns[u] && u ) leaf[r++] = u ; 222 } 223 h = t = 0 ; 224 que[t++] = rt ; 225 siz[0] = 0 ; 226 while (h < t) 227 { 228 u = que[h++] ; 229 for(i = head[u] ; i != -1 ; i = e[i].next) 230 { 231 to = e[i].to ; 232 if(to != fa[u]) 233 { 234 if(siz[son[u]] < siz[to]) son[u] = to ; 235 que[t++] = to ; 236 } 237 } 238 } 239 } 240 void BFS_cutLink(int rt, int tp){ 241 int i, u, to, h = 0, t = 0 ; 242 que[t++] = rt ; 243 while (h < t) 244 { 245 u = que[h++] ; 246 w[u] = ++cnt ; top[u] = u ; 247 to = son[u] ; 248 while (to) 249 { 250 w[to] = ++cnt ; top[to] = u ; 251 for(i = head[to] ; i != -1 ; i = e[i].next) 252 if(e[i].to != fa[to] && e[i].to != son[to]) que[t ++] = e[i].to ; 253 to = son[to] ; 254 } 255 for(i = head[u] ; i != -1 ; i = e[i].next) 256 { 257 to = e[i].to ; 258 if(to != fa[u] && to != son[u]) que[t++] = to ; 259 } 260 } 261 } 262 3. 非直接合并查询:树上最长上升子序列 263 /*********************线段树成段更新最长上升子序列*************************/ 264 void Up(int step){ 265 L[step].lx = L[lson].lx + ( (L[lson].lx==L[lson].len && val[L[rson].left] > val[L[lson].right])?L[rson].lx:0) ; 266 L[step].rx = L[rson].rx + ((L[rson].rx==L[rson].len &&val[L[rson].left] > val[L[lson].right])?L[lson].rx:0) ; 267 L[step].mx = max(max(L[lson].mx,L[rson].mx),val[L[rson].left] 268 > val[L[lson].right]?(L[lson].rx+L[rson].lx):0); 269 270 L[step].dlx = L[lson].dlx + ( (L[lson].dlx == L[lson].len && val[L[rson].left] < val[L[lson].right]) ? L[rson].dlx : 0 ); 271 L[step].drx = L[rson].drx + ((L[rson].drx == L[rson].len && val[L[rson].left] < val[L[lson].right]) ? L[lson].drx : 0 ) ; 272 L[step].dmx = max(max(L[lson].dmx,L[rson].dmx),val[L[rson].left] 273 < val[L[lson].right] ? (L[lson].drx+L[rson].dlx) : 0 ) ; 274 } 275 void build(int step,int l,int r){ 276 L[step].left=l; 277 L[step].right=r; 278 L[step].len = r-l+1 ; 279 L[step].mid=(l+r)/2; 280 if(l==r) 281 { 282 L[step].lx = L[step].rx = L[step].mx = 1 ; 283 L[step].dlx =L[step].drx = L[step].dmx = 1 ; 284 return ; 285 } 286 …… ; 287 } 288 inline void unionNode(int l, int r, int ar ){ 289 L[ar].lx = L[l].lx + ((L[l].lx==L[l].len && val[L[r].left] 290 > val[L[l].right]) ? L[r].lx : 0) ; 291 L[ar].rx = L[r].rx + ((L[r].rx==L[r].len && val[L[r].left] 292 > val[L[l].right]) ? L[l].rx : 0) ; 293 L[ar].mx = max(max(L[l].mx,L[r].mx),val[L[r].left] 294 > val[L[l].right]?(L[l].rx+L[r].lx):0); 295 296 L[ar].dlx = L[l].dlx + ((L[l].dlx == L[l].len && val[L[r].left] 297 < val[L[l].right]) ? L[r].dlx : 0 ); 298 L[ar].drx = L[r].drx + ((L[r].drx == L[r].len && val[L[r].left] 299 < val[L[l].right]) ? L[l].drx : 0 ) ; 300 L[ar].dmx = max(max(L[l].dmx,L[r].dmx),val[L[r].left] < val[L[l].right] 301 ? (L[l].drx+L[r].dlx) : 0 ) ; 302 L[ar].left = L[l].left ; 303 L[ar].right = L[r].right ; 304 L[ar].len = L[l].len + L[r].len ; 305 } 306 int query(int step,int l,int r){ 307 if(l==L[step].left&&r==L[step].right) return step ; 308 …… ; 309 else { 310 int lt = query(lson,l,L[step].mid); 311 int rt = query(rson,L[step].mid+1,r); 312 ++scnt ; 313 unionNode(lt, rt, scnt) ; 314 return scnt ; 315 } 316 } 317 /*************************树链剖分*************************/ 318 inline int unionAns(int l, int r){ 319 int tmp = max(L[l].dmx, L[r].mx), ans ; 320 if(val[L[l].left] < val[L[r].left]) ans = L[r].lx + L[l].dlx ; 321 else ans = 0 ; 322 ans = max(tmp, ans) ; 323 return ans ; 324 } 325 int getAns(int u, int v){ 326 if(u == v) return L[query(1, w[u], w[u])].mx ; 327 int tu = top[u], tv = top[v] ; 328 int ar, tr, ur, vr ; 329 scnt = 4*cnt +1; 330 ar = ++scnt ; ur = -1 ; vr = -1 ; 331 while (tu != tv) 332 { 333 if(dep[tu] > dep[tv])//calculate the link tu -> u. 334 { 335 tr = query(1, w[tu], w[u]) ; 336 if(ur == -1) ur = tr ; 337 else { 338 ++scnt ; 339 unionNode(tr, ur, scnt); //tr is left node. 340 ur = scnt ; 341 } 342 u = fa[tu] ; tu = top[u] ; 343 } 344 else { 345 tr = query(1, w[tv], w[v]) ; 346 if(vr == -1) vr = tr ; 347 else { 348 ++scnt ; 349 unionNode(tr, vr, scnt) ; // tr is left node. 350 vr = scnt ; 351 } 352 v = fa[tv] ; tv = top[v] ; 353 } 354 } 355 if(dep[u] >= dep[v])// v is root. 356 { 357 tr = query(1, w[v], w[u]) ; 358 if(ur == -1) ur = tr ; 359 else { 360 scnt ++ ; 361 unionNode(tr, ur, scnt) ; 362 ur = scnt ; 363 } 364 u = v ; 365 } 366 else { 367 tr = query(1, w[u], w[v]) ; 368 if(vr == -1) vr = tr ; 369 else { 370 ++scnt ; 371 unionNode(tr, vr, scnt) ; 372 vr = scnt ; 373 } 374 v = u ; 375 } 376 if(ur == -1) return L[vr].mx ; 377 else if(vr == -1) return L[ur].dmx ; 378 return unionAns(ur, vr) ; // calculate the answer of u->v 379 } 380 4. 树上最大字段和 381 /*********************线段树最大子段和*************************/ 382 inline void Up(int rt){ 383 sum[rt] = sum[rt<<1] + sum[rt<<1|1] ; 384 lx[rt] = max(lx[rt<<1|1], lx[rt<<1] + sum[rt<<1|1]) ; 385 rx[rt] = max(rx[rt<<1], rx[rt<<1|1] + sum[rt<<1]) ; 386 mx[rt] = max(mx[rt<<1], mx[rt<<1|1]) ;//不合并 387 mx[rt] = max(mx[rt], lx[rt<<1] + rx[rt<<1|1]) ; //合并 388 } 389 inline void Down(int rt, int L, int R){ 390 if(d[rt] != INF) 391 { 392 int x = d[rt] ; 393 int mid = (L+R) >> 1 ; 394 d[rt] = INF ; 395 d[rt<<1] = d[rt<<1|1] = x ; 396 sum[rt<<1] = (LL)x*(mid-L+1) ; 397 sum[rt<<1|1] = (LL)x*(R-mid) ; 398 lx[rt<<1] = rx[rt<<1] = mx[rt<<1] = x > 0 ? sum[rt<<1] : 0 ; 399 lx[rt<<1|1] = rx[rt<<1|1] = mx[rt<<1|1] = x > 0 ? sum[rt<<1|1] : 0 ; 400 } 401 } 402 inline void unionNode(int l, int r, int ar ){ 403 sum[ar] = sum[l] + sum[r] ; 404 lx[ar] = max(lx[r], lx[l]+sum[r]) ; 405 rx[ar] = max(rx[l], rx[r]+sum[l]) ; 406 mx[ar] = max(mx[l], mx[r]) ; 407 mx[ar] = max(mx[ar], lx[l]+rx[r]) ; 408 } 409 void build(int rt, int l, int r){ 410 d[rt] = INF ; 411 if(l == r) 412 { 413 sum[rt] = lx[rt] = rx[rt] = mx[rt] = val[l] ; 414 return ; 415 } 416 …… ; 417 } 418 void updata(int rt, int L, int R, int l, int r, int x){ 419 if(L == l && r == R) 420 { 421 sum[rt] = (R-L+1)*x ; 422 lx[rt] = rx[rt] = mx[rt] = x > 0 ? sum[rt] : 0 ; 423 d[rt] = x ; 424 return ; 425 } 426 Down(rt, L, R) ; 427 …… ; 428 } 429 int query(int rt, int L, int R, int l, int r){ 430 if(L == l && R == r) return rt ; 431 Down(rt, L, R) ; 432 …… ; 433 else { 434 int x = query(rt<<1, L, mid, l, mid) ; 435 int y = query(rt<<1|1, mid+1, R, mid+1, r) ; 436 ++scnt ; 437 unionNode(x, y, scnt) ; 438 return scnt ; 439 } 440 } 441 /*************************树链剖分*************************/ 442 inline void unionAns(int x, int y, int ar){ 443 mx[ar] = max(mx[x], mx[y]) ; 444 mx[ar] = max(mx[ar], rx[x]+rx[y]) ; 445 } 446 int getAns(int u, int v){ 447 if(u == v) return query(1, 1, cnt, w[u], w[u]) ; 448 int tu = top[u], tv = top[v] ; 449 int ar, tr, ur, vr ; 450 scnt = 4*cnt +1; 451 ar = ++scnt ; ur = -1 ; vr = -1 ; 452 while (tu != tv) 453 { 454 if(dep[tu] > dep[tv])//calculate the link tu -> u. 455 { 456 tr = query(1, 1, cnt, w[tu], w[u]) ; 457 if(ur == -1) ur = tr ; 458 else { 459 ++scnt ; 460 unionNode(tr, ur, scnt); //tr is left node. 461 ur = scnt ; 462 } 463 u = fa[tu] ; tu = top[u] ; 464 } 465 else { 466 tr = query(1, 1, cnt, w[tv], w[v]) ; 467 if(vr == -1) vr = tr ; 468 else { 469 ++scnt ; 470 unionNode(tr, vr, scnt) ; // tr is left node. 471 vr = scnt ; 472 } 473 v = fa[tv] ; tv = top[v] ; 474 } 475 } 476 if(dep[u] >= dep[v]) 477 { 478 tr = query(1, 1, cnt, w[v], w[u]) ; 479 if(ur == -1) ur = tr ; 480 else { 481 scnt ++ ; 482 unionNode(tr, ur, scnt) ; 483 ur = scnt ; 484 } 485 u = v ; 486 } 487 else { 488 tr = query(1, 1, cnt, w[u], w[v]) ; 489 if(vr == -1) vr = tr ; 490 else { 491 ++scnt ; 492 unionNode(tr, vr, scnt) ; 493 vr = scnt ; 494 } 495 v = u ; 496 } 497 if(ur == -1) return vr ; 498 else if(vr == -1) return ur ; 499 unionAns(ur, vr, ar) ; // calculate the answer of u->v 500 return ar ; 501 } 502 四、持久化线段树 503 /*******************静态 Kth number ***************************************/ 504 void build(int &rt, int l, int r ){ 505 rt = ++tot ; 506 sum[rt] = 0 ; 507 if(l >= r) return ; 508 …… ; 509 } 510 void updata(int &rt, int pre, int l, int r, int i, int v){ 511 rt = ++tot ; 512 ls[rt] = ls[pre] ; rs[rt] = rs[pre] ; sum[rt] = sum[pre] + v ; 513 if(l >= r ) return ; 514 int mid = l+r >> 1 ; 515 if(mid >= i ) updata(ls[rt], ls[pre], l, mid, i, v) ; 516 else updata(rs[rt], rs[pre], mid+1, r, i, v) ; 517 } 518 int query(int R, int L, int l, int r, int k){ 519 if(l >= r) return l ; 520 int t = sum[ls[R]] - sum[ls[L]] ; 521 int mid = l+r >> 1 ; 522 if(t >= k) return query(ls[R], ls[L], l, mid, k) ; 523 else return query(rs[R], rs[L], mid+1, r, k-t) ; 524 } 525 /***************************************************************/ 526 void solve(){ 527 sort(ord+1, ord+1+n, comp) ; 528 cnt = rk[ord[1]] = 1 ; 529 nar[cnt] = ar[ord[1]] ; 530 for(i = 2 ; i <= n ; i ++) 531 { 532 if(ar[ord[i]] != ar[ord[i-1]]) 533 { 534 rk[ord[i]] = ++cnt ; 535 nar[cnt] = ar[ord[i]] ; 536 } 537 else rk[ord[i]] = cnt ; 538 } 539 tot = 0 ; 540 build(T[0], 1, cnt) ; 541 for(i = 1 ; i <= n ; i ++) updata(T[i], T[i-1], 1, cnt, rk[i], 1) ; 542 for(i = 1 ; i <= m ; i ++) 543 { 544 scanf("%d %d %d", &l, &r, &k) ; 545 ans = query(T[r], T[l-1], 1, cnt, k) ; 546 printf("%d ", nar[ans]) ;//离散后的数组 547 } 548 } 549 } 550 五、KD树 551 #define N 50005 552 #define MID(x,y) ( (x + y)>>1 ) 553 using namespace std ; 554 typedef long long LL ; 555 struct Point{ 556 int x[5]; 557 LL dis; 558 Point(){ 559 for(int i = 0 ; i < 5 ; i++) x[i] = 0 ; 560 dis = 9223372036854775807LL ; 561 } 562 friend bool operator < (const Point &a, const Point &b) 563 { return a.dis < b.dis ; } 564 }; 565 priority_queue <Point, vector<Point> > res ; 566 LL dist2(const Point &a, const Point &b, int k) { 567 //距离的*方,开根号很耗时,能不开就不开 568 LL ans = 0; 569 for (int i = 0; i < k; i++) 570 //一开始这儿写的i < 5,WA了N次。。。原本以为只要初始值设0就无所谓, 571 ans += (a.x[i] - b.x[i]) * (a.x[i] - b.x[i]); 572 //但发现Point有个全局变量,在多case下会出错。。。 573 return ans; 574 } 575 int ddiv; 576 bool cmpX(const Point &a, const Point &b){return a.x[ddiv] < b.x[ddiv];} 577 struct KDTree { 578 Point p[N]; //空间内的点 579 int Div[N]; 580 //记录区间是按什么方式划分(分割线*行于x轴还是y轴, ==1*行y轴切;==0*行x轴切) 581 int k; //维数 582 int m; //*邻 583 int getDiv(int l, int r) { //寻找区间跨度最大的划分方式 584 map <int, int> ms; 585 int minx[5],maxx[5]; 586 for (int i = 0; i < k; i++) 587 { 588 ddiv = i; 589 minx[i] = min_element(p + l, p + r + 1, cmpX)->x[i]; 590 maxx[i] = max_element(p + l, p + r + 1, cmpX)->x[i]; 591 ms[maxx[i] - minx[i]] = i; 592 } 593 map <int ,int>::iterator pm = ms.end(); 594 pm--; 595 return pm->second; 596 } 597 void build(int l, int r) { //记得先把p备份一下。 598 if (l > r) return; 599 int mid = MID(l,r); 600 Div[mid] = getDiv(l,r); 601 ddiv = Div[mid]; 602 nth_element(p + l, p + mid, p + r + 1, cmpX); 603 build(l, mid - 1); 604 build(mid + 1, r); 605 } 606 void findk(int l, int r, Point a) {//k(m)*邻,查找k*点的*方距离 607 if (l > r) return; 608 int mid = MID(l,r); 609 LL dist = dist2(a, p[mid], k); 610 if (dist >= 0) 611 { 612 p[mid].dis = dist; 613 res.push(p[mid]); 614 while ((int)res.size() > m) 615 res.pop(); 616 } 617 LL d = a.x[Div[mid]] - p[mid].x[Div[mid]]; 618 int l1, l2, r1, r2; 619 l1 = l , l2 = mid + 1; 620 r1 = mid - 1, r2 = r; 621 if (d > 0) 622 swap(l1, l2), swap(r1, r2); 623 findk(l1, r1, a); 624 if ((int)res.size() < m || d*d < res.top().dis ) 625 findk(l2, r2, a); 626 } 627 }; 628 Point pp[N]; 629 KDTree kd; 630 int solve(){ 631 for (int i = 0; i < n; i++) 632 for (int j = 0; j < kd.k; j++) 633 { 634 scanf("%d", &pp[i].x[j]); 635 kd.p[i] = pp[i]; 636 } 637 kd.build(0, n - 1); 638 int t = 10 ; 639 while(t--) 640 { 641 Point a; 642 for (int i = 0; i < kd.k; i++)scanf("%d", &a.x[i]); 643 scanf("%d", &kd.m); 644 kd.findk(0, n - 1, a); 645 printf("the closest %d points are: ", kd.m); 646 Point ans[11]; 647 for (int i = 0; !res.empty(); i++) 648 { 649 ans[i] = res.top(); 650 res.pop(); 651 } 652 for (int i = kd.m - 1; i >= 0; i--) 653 { 654 for (int j = 0; j < kd.k - 1; j++) 655 printf("%d ", ans[i].x[j]); 656 printf("%d ", ans[i].x[kd.k - 1]); 657 } 658 } 659 六、最远manhattan距离 660 int query(int rt, int p, int s) //维护每个状态的最大值、最小值。 661 void getTable(int pos){//每个点有sta个状态 662 int i, j, t ; 663 for(i = 0 ; i < sta ; i ++) 664 { 665 t = i ; 666 tmp[i] = 0 ; 667 for(j = 1 ; j <= k ; j ++) 668 { 669 if(t&1) tmp[i] += ar[pos].x[j] ; 670 else tmp[i] -= ar[pos].x[j] ; 671 t >>= 1 ; 672 } 673 } 674 } 675 int solve(){ 676 sta = 1<<k ; //K维*面 677 build(1, 1, q) ;//将每个点的sta个状态插入树中 678 cnt = 0 ; 679 for(i = 1 ; i <= q ; i ++) 680 { 681 if(cnt < 2){puts("0") ;continue ; } 682 int ans = 0 ; 683 for(j = 0 ; j < sta ; j ++) 684 { 685 mxs = query(1, j, 1) ; //查询最大值; 686 mns = query(1, j, 0) ; //查询最小值; 687 ans = ans > mxs - mns ? ans : mxs-mns ; 688 } 689 printf("%d ", ans) ; 690 } 691 七、LCA & RMQ & 树状数组 692 /*****************************LCA*******************************/ 693 struct QNode{ 694 int from, to, next, no ; 695 }qe[MAXN]; 696 int cnt ; 697 int qhead[MAXN], pre[MAXN], LCA[MAXN] ; 698 inline void addQEdge(int a,int b,int c){ 699 qe[++cnt].from = a ; 700 qe[cnt].to = b ; 701 qe[cnt].next = qhead[a] ; 702 qe[cnt].no = c ; 703 qhead[a] = cnt; 704 } 705 int find(int x){ 706 if(x != pre[x]) pre[x]=find(pre[x]); 707 return pre[x]; 708 } 709 void tarjan(int u){ 710 int j, v ; 711 pre[u] = u ; 712 for(j = qhead[u] ; j != -1 ; j = qe[j].next) 713 { 714 v = qe[j].to; 715 LCA[qe[j].no] = find(v) ; 716 } 717 for(j = head[u] ; j != -1 ;j = e[j].next) 718 { 719 v = e[j].to ; 720 tarjan(v) ; 721 pre[v] = u ; 722 } 723 } 724 /*****************************RMQ*******************************/ 725 int mn[MAXN][18] ; 726 void rmq_init(int num){ 727 int i , j ; 728 for(j = 1 ; j <= num ; j ++ ) mn[j][0] = height[j] ; 729 int m = floor(log((double)num)/log(2.0)) ; 730 for(i = 1 ; i <= m ; i ++ ) 731 { 732 for(j = num ; j > 0 ; j -- ) 733 { 734 mn[j][i] = mn[j][i-1] ; 735 if(j+(1<<(i-1)) <= num) 736 mn[j][i] = min( mn[j][i] , mn[j+(1<<(i-1))][i-1]) ; 737 } 738 } 739 } 740 int rmq(int l,int r){ 741 int m = floor(log((double)(r-l+1))/log(2.0)) ; 742 int a = min(mn[l][m], mn[r-(1<<m)+1][m] ) ; 743 return a ; 744 } 745 /*****************************树状数组*******************************/ 746 int Lowbit(int t){ //求最小幂2^k 747 return t&(-t) ; 748 } 749 int Sum(int end) { //求前n项和 750 int sum = 0 ; 751 while(end > 0) 752 { 753 sum += c[end]; 754 end -= Lowbit(end); 755 } 756 return sum; 757 } 758 void plus(int pos , int n, int num){ //对某个元素进行加法操作 759 while(pos <= n) 760 { 761 c[pos] += num; 762 pos += Lowbit(pos); 763 } 764 } 765 八、划分树 766 int SU[100001]; 767 int U[21][100001]; 768 int toL[21][100001]; 769 int n,m,a,b,k,t; 770 inline int cmp(const void *a,const void *b){return *((int *)a) - *((int *)b) ;} 771 void buildtree(int l,int r,int d){ 772 int i ; 773 if (l==r) return; 774 int mid = (l+r)>>1 , nowl = l , nowr = mid+1 , midtol = 0 ; 775 for (i = mid ;i>=l && SU[i] == SU[mid] ; i--) ++midtol ; 776 for (i = l ; i <= r ; i++) 777 { 778 toL[d][i] = i==l ? 0 : toL[d][i-1]; 779 if (U[d][i] < SU[mid]) 780 { 781 U[d+1][nowl++] = U[d][i]; 782 ++toL[d][i]; 783 } 784 else if (U[d][i]==SU[mid] && midtol) 785 { 786 U[d+1][nowl++] = U[d][i]; 787 ++toL[d][i]; 788 --midtol; 789 } 790 else U[d+1][nowr++] = U[d][i]; 791 } 792 buildtree(l,mid,d+1); 793 buildtree(mid+1,r,d+1); 794 } 795 int answer(int a,int b,int k){ 796 int l = 1,r = n,d = 0; 797 int ls,rs,mid; 798 while (a != b) 799 { 800 ls = a==l ? 0 : toL[d][a-1]; 801 rs = toL[d][b]; 802 mid = (l+r)>>1; 803 if (k <= rs - ls) 804 { 805 a = l+ls; 806 b = l+rs-1; 807 r = mid; 808 } 809 else { 810 a = mid+1+a-l-ls; 811 b = mid+1+b-l-rs; 812 k -= rs-ls; 813 l = mid+1; 814 } 815 ++d; 816 } 817 return U[d][a]; 818 } 819 int solve(){ 820 for (i=1;i<=n;i++) 821 { 822 scanf("%d",&t); 823 SU[i]=U[0][i]=t; 824 } 825 sort(SU+1, SU+1+n) ; 826 buildtree(1 , n , 0 ); 827 printf("%d ",answer(a, b, k ) ); 828 }