acm数据结构整理

  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     }
View Code

 

posted @ 2015-03-12 14:32  安月天下  阅读(427)  评论(0编辑  收藏  举报