• bzoj 1468


    大概思路:树点分治,重心树中每个重心维护一个总的平衡树,树中保存属于该重心的点到该重心的距离,然后对于去掉该重心后形成的子树分别再保存一份。

    用这种方式实现的话,还可以支持修改与多次查询,每次操作都是O(logn*logn)

    感悟:

    点分治正如一个前辈说的,是“借助”重心的力量,来维护与查询与某点距离相关的问题,我们知道点u到它各个重心的距离关系,各个重心又保存了所有属于它的点的信息,可以证明,一个点至多属于O(logn)个重心,所有重心拥有的点总和为O(nlogn)。

    本质上来说,树的点分治是通过找重心来对树分治,然后建立了一种层次关系(想象一下,找出一棵树的重心,然后在3维空间向上提升,幷让重心向剩下的各块的重心连边,然后再将各块分层,这样就形成了这种层次关系,表现为树结构就是所谓的重心树)。

      1 /**************************************************************
      2     Problem: 1468
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:6536 ms
      7     Memory:54384 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <vector>
     12 #include <map>
     13 #define fprintf(...)
     14 #define N 40010
     15 #define S 2000000
     16 using namespace std;
     17  
     18 struct Stat {
     19     int c, d, s;
     20     Stat( int c, int d, int s ):c(c),d(d),s(s){}
     21 };
     22 struct Splay {
     23     static int son[S][2], pre[S], key[S], siz[S], ntot;
     24     int root;
     25     void init() { root=0; }
     26     inline void update( int nd ) {
     27         siz[nd] = siz[son[nd][0]]+siz[son[nd][1]]+1;
     28     }
     29     void rotate( int nd, int d ) {
     30         int p=pre[nd];
     31         int s=son[nd][!d];
     32         int ss=son[s][d];
     33          
     34         son[nd][!d] = ss;
     35         son[s][d] = nd;
     36         if( p ) son[p][ nd==son[p][1] ] = s;
     37         else root = s;
     38  
     39         pre[nd] = s;
     40         pre[s] = p;
     41         if( ss ) pre[ss] = nd;
     42          
     43         update( nd );
     44         update( s );
     45     }
     46     void splay( int nd, int top=0 ) {
     47         while( pre[nd]!=top ) {
     48             int p = pre[nd];
     49             int nl = nd==son[p][0];
     50             if( pre[p]==top ) {
     51                 rotate( p, nl );
     52             } else {
     53                 int pp = pre[p];
     54                 int pl = p==son[pp][0];
     55                 if( nl==pl ) {
     56                     rotate( pp, pl );
     57                     rotate( p, nl );
     58                 } else {
     59                     rotate( p, nl );
     60                     rotate( pp, pl );
     61                 }
     62             }
     63         }
     64     }
     65     int newnode( int p, int k ) {
     66         int nd = ++ntot;
     67         son[nd][0] = son[nd][1] = 0;
     68         pre[nd] = p;
     69         key[nd] = k;
     70         siz[nd] = 1;
     71         return nd;
     72     }
     73     void insert( int k ) {
     74         if( !root ) {
     75             root = newnode( 0, k );
     76             return;
     77         }
     78         int nd = root;
     79         while( son[nd][ k>key[nd] ] ) nd=son[nd][ k>key[nd] ];
     80         son[nd][ k>key[nd] ] = newnode( nd, k );
     81         splay( son[nd][ k>key[nd] ] );
     82     }
     83     int query( int k ) {
     84         int nd=root;
     85         int lnd;
     86         int rt = 0;
     87         while(nd) {
     88             lnd = nd;
     89             if( key[nd]>k ) {
     90                 nd = son[nd][0];
     91             } else {
     92                 rt += siz[son[nd][0]]+1;
     93                 nd = son[nd][1];
     94             }
     95         }
     96         splay( lnd );
     97         return rt;
     98     }
     99 };
    100 int Splay::son[S][2], Splay::pre[S], Splay::key[S], Splay::siz[S], Splay::ntot;
    101  
    102  
    103 int n, qdis;
    104 vector<int> g[N], ww[N];
    105 vector<Stat> st[N];
    106 map<int,Splay > spy[N];
    107 int vis[N], anc[N], siz[N], bac[N], dis[N];
    108 int qu[N], bg, ed;
    109  
    110 void build( int rt ) {
    111     /* find the core of the block containing rt */
    112     qu[bg=ed=1] = rt;
    113     anc[rt] = rt;
    114     siz[rt] = bac[rt] = 0;
    115     while( ed>=bg ) {
    116         int u=qu[bg++];
    117         for( int t=0; t<g[u].size(); t++ ) {
    118             int v=g[u][t];
    119             if( vis[v] || v==anc[u] ) continue;
    120             qu[++ed] = v;
    121             anc[v] = u;
    122             siz[v] = bac[v] = 0;
    123         }
    124     }
    125     for( int i=ed; i>=1; i-- ) {
    126         int u=qu[i];
    127         int p=anc[u];
    128         siz[u]++;
    129         siz[p] += siz[u];
    130         if( bac[p]<siz[u] ) bac[p]=siz[u];
    131     }
    132     for( int i=ed; i>=1; i-- ) {
    133         int u=qu[i];
    134         if( bac[u]<siz[rt]-siz[u] ) bac[u]=siz[rt]-siz[u];
    135     }
    136     for( int i=ed; i>=1; i-- ) {
    137         int u=qu[i];
    138         if( bac[u]<bac[rt] ) rt=u;
    139     }
    140     /* statistics the info of the block */
    141     spy[rt][0].init();
    142     spy[rt][0].insert( 0 );
    143     st[rt].push_back( Stat(rt,0,0) );
    144     vis[rt] = true;
    145     fprintf( stderr, "%d as core
    ", rt );
    146     for( int tm=0; tm<g[rt].size(); tm++ ) {
    147         int r=g[rt][tm], w=ww[rt][tm];
    148         if( vis[r] ) continue;
    149         qu[bg=ed=1] = r;
    150         anc[r] = rt;
    151         dis[r] = w;
    152         while( ed>=bg ) {
    153             int u=qu[bg++];
    154             for( int t=0; t<g[u].size(); t++ ) {
    155                 int v=g[u][t], w=ww[u][t];
    156                 if( vis[v] || v==anc[u] ) continue;
    157                 qu[++ed] = v;
    158                 anc[v] = u;
    159                 dis[v] = dis[u]+w;
    160             }
    161         }
    162         spy[rt][r].init();
    163         for( int i=ed; i>=1; i-- ) {
    164             int u=qu[i];
    165             spy[rt][0].insert( dis[u] );
    166             spy[rt][r].insert( dis[u] );
    167             st[u].push_back( Stat(rt,dis[u],r) );
    168         }
    169         build( r );
    170     }
    171 }
    172  
    173 int main() {
    174     scanf( "%d", &n );
    175     for( int i=1,u,v,w; i<n; i++ ) {
    176         scanf( "%d%d%d", &u, &v, &w );
    177         g[u].push_back( v );
    178         g[v].push_back( u );
    179         ww[u].push_back( w );
    180         ww[v].push_back( w );
    181     }
    182     scanf( "%d", &qdis );
    183     build(1);
    184     for( int u=1; u<=n; u++ ) {
    185         fprintf( stderr, "Stat of %d:
    ", u );
    186         for( int t=0; t<st[u].size(); t++ ) {
    187             fprintf( stderr, "core=%d dis=%d subcore:%d
    ", st[u][t].c, st[u][t].d, st[u][t].s );
    188         }
    189         fprintf( stderr, "
    " );
    190     }
    191      
    192     int ans = 0;
    193     for( int u=1; u<=n; u++ ) {
    194         int tans=0;
    195         for( int t=0; t<st[u].size(); t++ ) {
    196             Stat &s = st[u][t];
    197             tans += spy[s.c][0].query( qdis-s.d )- (s.s?spy[s.c][s.s].query( qdis-s.d ):0);
    198         }
    199         fprintf( stderr, "%d added %d
    ", u, tans-1 );
    200         ans += tans-1;
    201     }
    202     printf( "%d
    ", ans/2 );
    203 }
    View Code
  • 相关阅读:
    联想 Vibe Shot(Z90-3) 免recovery 获取ROOT权限 救砖 VIBEUI V3.1_1625
    联想 Z5S(L78071)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.370
    联想 Z5(L78011) 免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 10.5.254
    联想 S5 Pro(L78041)免解锁BL 免rec 保留数据 ROOT Magisk Xposed 救砖 ZUI 5.0.123
    第二阶段 冲刺八
    第二阶段 冲刺七
    第二阶段 冲刺六
    第二阶段 冲刺五
    代码大全阅读笔记03
    学习进度十二
  • 原文地址:https://www.cnblogs.com/idy002/p/4369703.html
Copyright © 2020-2023  润新知