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
  • 相关阅读:
    发布基于C#的机器视觉库 *版本1.0.1*
    5月28日介绍这几年机器学习经历的讲演材料
    初识 PLINQ
    推荐博文:鸟瞰淘宝开放平台
    发布一款基于C#的网络爬虫程序
    发布基于C#的网络爬虫程序 *版本1.0.1*
    神秘园与班得瑞
    发布一款基于C#的机器视觉库
    《阿凡达》观影归来
    朝花夕识 和 Google Goggles 的差别
  • 原文地址:https://www.cnblogs.com/idy002/p/4366969.html
Copyright © 2011-2022 走看看