zoukankan      html  css  js  c++  java
  • 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
    ", 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     }
    View Code
  • 相关阅读:
    HDU5873
    HDU5874
    HDU1565(状态压缩dp)
    POJ2774(二分+哈希)
    HDU4474
    HDU2602(背包)
    单链表
    POJ2503(hash)
    POJ1200(hash)
    顺序表
  • 原文地址:https://www.cnblogs.com/xieyue/p/4332348.html
Copyright © 2011-2022 走看看