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\n", 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:\n", 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\n", 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\n", 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\n",answer(a, b, k ) );
828 }