zoukankan      html  css  js  c++  java
  • hdu 4918

    第一道树的点分治。

    感谢:

    http://blog.csdn.net/u013368721/article/details/40887575

    首先,找出原图的重心(最大子树大小最小的点(如果作为根)),去掉它后原图就分成了若干的森林,再在对应的森林中找出重心,递归这个过程(只有一个点时返回)。

    这样,我们就可以根据重心的所属关系,建立出一棵树,显然原图的重心就是这颗树的重心,每个重心对应一些点(就是去掉该重心前,该重心联通块中的所有点)。

    容易看出,因为每次选的是重心,所以树每次至少会分成两块(最坏情况),考虑我们根据重心所属关系建立出的树,最多有O(logn)层,每层找重心总的复杂度是O(n)(因为每层重心对应的点是O(n)级别的),所以建立这个关系是O(nlogn)的复杂度。

    应前辈的称呼,我们就叫建立出的这颗很多重心的树为重心树。

    对于这道题,我们可以给重心树的每个节点建立一个树状数组,树状数组下标为到重心的距离,值为点的权值,将重心对应的点都放到这个树状数组中(因为最大距离就是该重心对应的点数-1,所以树状数组的大小就设成该重心对应的点数),因为一层对应的所有重心对应的点数最多为O(n),所以总共占用的空间为O(nlogn)。然后还要根据这个重心的不同子重心分开记录一下这个东西,用于去重。

      1 #include <cstdio>
      2 #include <vector>
      3 #include <map>
      4 #define N 100010
      5 using namespace std;
      6 
      7 struct Stat {
      8     int r, d, s;
      9     Stat( int r, int d, int s ):r(r),d(d),s(s){}
     10 };
     11 struct Bit {
     12     int n;
     13     vector<int> vv;
     14     void init( int n ) {
     15         this->n = n;
     16         vv.resize( n+1 );
     17         for( int t=1; t<=n; t++ ) vv[t] = 0;
     18     }
     19     void modify( int pos, int delta ) {
     20         pos++;
     21         for( int i=pos; i<=n; i+=i&-i )
     22             vv[i]+=delta;
     23     }
     24     int query( int pos ) {
     25         int rt = 0;
     26         pos++;
     27         if( pos>n ) pos=n;
     28         for( int i=pos; i; i-=i&-i )
     29             rt += vv[i];
     30         return rt;
     31     }
     32 };
     33 
     34 int n, m;
     35 vector<int> g[N];
     36 vector<Stat> st[N];
     37 map<int,Bit > bit[N];
     38 int ww[N];
     39 int vis[N], siz[N], anc[N], bac[N], dis[N];
     40 int qu[N], beg, tail;
     41 
     42 void init( int n ) {
     43     for( int i=1; i<=n; i++ ) {
     44         g[i].clear();
     45         st[i].clear();
     46         bit[i].clear();
     47         vis[i] = false;
     48     }
     49 }
     50 void build( int root ) {
     51     qu[beg=tail=0] = root;
     52     anc[root] = root;
     53     siz[root] = bac[root] = 0;
     54     while( tail>=beg ) {
     55         int u=qu[beg++];
     56         for( int t=0; t<g[u].size(); t++ ) {
     57             int v=g[u][t];
     58             if( v==anc[u] || vis[v] ) continue;
     59             qu[++tail] = v;
     60             anc[v] = u;
     61             siz[v] = bac[v] = 0;
     62         }
     63     }
     64     for( int i=tail; i; i-- ) {
     65         int v=qu[i];
     66         int u=anc[v];
     67         siz[v]++;
     68         siz[u]+=siz[v];
     69         if( siz[v]>bac[u] ) bac[u]=siz[v];
     70     }
     71     for( int i=0; i<=tail; i++ ) {
     72         int u = qu[i];
     73         if( siz[root]-siz[u]>bac[u] ) bac[u]=siz[root]-siz[u];
     74     }
     75     for( int i=0; i<=tail; i++ ) {
     76         int u = qu[i];
     77         if( bac[u]<bac[root] ) root=u;
     78     }
     79     //----------------   found the core   -------------------//
     80     bit[root][0].init( tail+1 );
     81     bit[root][0].modify( 0, ww[root] );
     82     st[root].push_back( Stat(root,0,0) );
     83     vis[root] = true;
     84 
     85 
     86     anc[root] = root;
     87     for( int t=0; t<g[root].size(); t++ ) {
     88         int sr = g[root][t];
     89         if( vis[sr] ) continue;
     90         qu[beg=tail=0] = sr;
     91         dis[sr] = 1;
     92         anc[sr] = root;
     93         while( tail>=beg ) {
     94             int u=qu[beg++];
     95             for( int t=0; t<g[u].size(); t++ ) {
     96                 int v=g[u][t];
     97                 if( vis[v] || v==anc[u] ) continue;
     98                 qu[++tail] = v;
     99                 dis[v] = dis[u]+1;
    100                 anc[v] = u;
    101             }
    102         }
    103         bit[root][sr].init( tail+2 );
    104         for( int i=0; i<=tail; i++ ) {
    105             int u=qu[i];
    106             bit[root][0].modify( dis[u], ww[u] );
    107             bit[root][sr].modify( dis[u], ww[u] );
    108             st[u].push_back( Stat(root,dis[u],sr) );
    109         }
    110     }
    111     for( int t=0; t<g[root].size(); t++ ) {
    112         int v=g[root][t];
    113         if( vis[v] ) continue;
    114         build(g[root][t]);
    115     }
    116 }
    117 void modify( int u, int d ) {
    118     for( int t=0; t<st[u].size(); t++ ) {
    119         Stat &s = st[u][t];
    120         bit[s.r][0].modify( s.d, d );
    121         if( s.s ) bit[s.r][s.s].modify( s.d, d );
    122     }
    123 }
    124 int query( int u, int d ) {
    125     int rt = 0;
    126     for( int t=0; t<st[u].size(); t++ ) {
    127         Stat &s = st[u][t];
    128         if( d<s.d ) continue;
    129         int v = bit[s.r][0].query( d-s.d );
    130         rt += v;
    131         if( s.s ) {
    132             v = bit[s.r][s.s].query( d-s.d );
    133             rt -= v;
    134         }
    135     }
    136     return rt;
    137 }
    138 
    139 int main() {
    140     while(1) {
    141         if( scanf( "%d%d", &n, &m )!=2 ) return 0;
    142         init(n);
    143         for( int i=1; i<=n; i++ )
    144             scanf( "%d", ww+i );
    145         for( int i=1,u,v; i<n; i++ ) {
    146             scanf( "%d%d", &u, &v );
    147             g[u].push_back( v );
    148             g[v].push_back( u );
    149         }
    150         build(1);
    151         for( int i=1; i<=m; i++ ) {
    152             char ch[10];
    153             int u, d;
    154             scanf( "%s%d%d", ch, &u, &d );
    155             if( ch[0]=='!' ) {
    156                 modify( u, d-ww[u] );
    157                 ww[u] = d;
    158             } else {
    159                 printf( "%d
    ", query(u,d) );
    160             }
    161         }
    162     }
    163 }
    View Code
  • 相关阅读:
    Codeforces Round #344 (Div. 2) C. Report 其他
    Codeforces Round #344 (Div. 2) B. Print Check 水题
    Codeforces Round #344 (Div. 2) A. Interview 水题
    8VC Venture Cup 2016
    CDOJ 1280 772002画马尾 每周一题 div1 矩阵快速幂 中二版
    CDOJ 1280 772002画马尾 每周一题 div1 矩阵快速幂
    CDOJ 1279 班委选举 每周一题 div2 暴力
    每周算法讲堂 快速幂
    8VC Venture Cup 2016
    Educational Codeforces Round 9 F. Magic Matrix 最小生成树
  • 原文地址:https://www.cnblogs.com/idy002/p/4366969.html
Copyright © 2011-2022 走看看