第一道树的点分治。

感谢:

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

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

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

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

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

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

 #include <cstdio>
#include <vector>
#include <map>
#define N 100010
using namespace std; struct Stat {
int r, d, s;
Stat( int r, int d, int s ):r(r),d(d),s(s){}
};
struct Bit {
int n;
vector<int> vv;
void init( int n ) {
this->n = n;
vv.resize( n+ );
for( int t=; t<=n; t++ ) vv[t] = ;
}
void modify( int pos, int delta ) {
pos++;
for( int i=pos; i<=n; i+=i&-i )
vv[i]+=delta;
}
int query( int pos ) {
int rt = ;
pos++;
if( pos>n ) pos=n;
for( int i=pos; i; i-=i&-i )
rt += vv[i];
return rt;
}
}; int n, m;
vector<int> g[N];
vector<Stat> st[N];
map<int,Bit > bit[N];
int ww[N];
int vis[N], siz[N], anc[N], bac[N], dis[N];
int qu[N], beg, tail; void init( int n ) {
for( int i=; i<=n; i++ ) {
g[i].clear();
st[i].clear();
bit[i].clear();
vis[i] = false;
}
}
void build( int root ) {
qu[beg=tail=] = root;
anc[root] = root;
siz[root] = bac[root] = ;
while( tail>=beg ) {
int u=qu[beg++];
for( int t=; t<g[u].size(); t++ ) {
int v=g[u][t];
if( v==anc[u] || vis[v] ) continue;
qu[++tail] = v;
anc[v] = u;
siz[v] = bac[v] = ;
}
}
for( int i=tail; i; i-- ) {
int v=qu[i];
int u=anc[v];
siz[v]++;
siz[u]+=siz[v];
if( siz[v]>bac[u] ) bac[u]=siz[v];
}
for( int i=; i<=tail; i++ ) {
int u = qu[i];
if( siz[root]-siz[u]>bac[u] ) bac[u]=siz[root]-siz[u];
}
for( int i=; i<=tail; i++ ) {
int u = qu[i];
if( bac[u]<bac[root] ) root=u;
}
//---------------- found the core -------------------//
bit[root][].init( tail+ );
bit[root][].modify( , ww[root] );
st[root].push_back( Stat(root,,) );
vis[root] = true; anc[root] = root;
for( int t=; t<g[root].size(); t++ ) {
int sr = g[root][t];
if( vis[sr] ) continue;
qu[beg=tail=] = sr;
dis[sr] = ;
anc[sr] = root;
while( tail>=beg ) {
int u=qu[beg++];
for( int t=; t<g[u].size(); t++ ) {
int v=g[u][t];
if( vis[v] || v==anc[u] ) continue;
qu[++tail] = v;
dis[v] = dis[u]+;
anc[v] = u;
}
}
bit[root][sr].init( tail+ );
for( int i=; i<=tail; i++ ) {
int u=qu[i];
bit[root][].modify( dis[u], ww[u] );
bit[root][sr].modify( dis[u], ww[u] );
st[u].push_back( Stat(root,dis[u],sr) );
}
}
for( int t=; t<g[root].size(); t++ ) {
int v=g[root][t];
if( vis[v] ) continue;
build(g[root][t]);
}
}
void modify( int u, int d ) {
for( int t=; t<st[u].size(); t++ ) {
Stat &s = st[u][t];
bit[s.r][].modify( s.d, d );
if( s.s ) bit[s.r][s.s].modify( s.d, d );
}
}
int query( int u, int d ) {
int rt = ;
for( int t=; t<st[u].size(); t++ ) {
Stat &s = st[u][t];
if( d<s.d ) continue;
int v = bit[s.r][].query( d-s.d );
rt += v;
if( s.s ) {
v = bit[s.r][s.s].query( d-s.d );
rt -= v;
}
}
return rt;
} int main() {
while() {
if( scanf( "%d%d", &n, &m )!= ) return ;
init(n);
for( int i=; i<=n; i++ )
scanf( "%d", ww+i );
for( int i=,u,v; i<n; i++ ) {
scanf( "%d%d", &u, &v );
g[u].push_back( v );
g[v].push_back( u );
}
build();
for( int i=; i<=m; i++ ) {
char ch[];
int u, d;
scanf( "%s%d%d", ch, &u, &d );
if( ch[]=='!' ) {
modify( u, d-ww[u] );
ww[u] = d;
} else {
printf( "%d\n", query(u,d) );
}
}
}
}

hdu 4918的更多相关文章

  1. HDU 4918 Query on the subtree(动态点分治+树状数组)

    题意 给定一棵 \(n\) 个节点的树,每个节点有点权.完成 \(q\) 个操作--操作分两种:修改点 \(x\) 的点权.查询与 \(x\) 距离小于等于 \(d\) 的权值总和. \(1 \leq ...

  2. 胡小兔的OI日志3 完结版

    胡小兔的 OI 日志 3 (2017.9.1 ~ 2017.10.11) 标签: 日记 查看最新 2017-09-02 51nod 1378 夹克老爷的愤怒 | 树形DP 夹克老爷逢三抽一之后,由于采 ...

  3. hdu 4915 Parenthese sequence--2014 Multi-University Training Contest 5

    主题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4915 Parenthese sequence Time Limit: 2000/1000 MS (Ja ...

  4. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  6. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  7. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  8. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  9. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

随机推荐

  1. 【译】第二篇 SQL Server代理作业步骤和子系统

    本篇文章是SQL Server代理系列的第二篇,详细内容请参考原文. SQL Server代理作业由一系列的一个或多个作业步骤组成.一个作业步骤分配给一个特定的作业子系统(确定作业步骤去完成的工作). ...

  2. WordPress的SEO插件——WordPress SEO by yoast安装及使用

    插件:WordPress SEO by yoast 使用方法: 做好网站SEO一直是站长们的愿望,说简单也简单,但是说难也难,因为需要注意的地方太多,一个不小心被百度K了你都不知道怎么回事.这里和大家 ...

  3. Mysql储存过程3:if语句

    --if/else语句 if 条件 then SQL语句 else SQL语句elseifSQL语句 end if; create procedure test1( number int ) begi ...

  4. python基础===对字符串进行左右中对齐

    例如,有一个字典如下: >>> dic = { "name": "botoo", "url": "http:// ...

  5. iOS通知中心

    iOS通知中心 它是iOS程序内部的一种消息广播机制,通过它,可以实现无引用关系的对象之间的通信.通知中心他是基于观察者模式,它只能进行程序内部通信,不能跨应用程序进程通信. 当通知中心接受到消息后会 ...

  6. 配置Tomcat、maven远程部署调试总结。

    注意:可以搞两个环境,一个本地tomcat 一个服务器上的tomcat ,然后都采用如下配置.这样就可以 在本地调试,调试好后,再发布到服务器端.非常方便.  ==================== ...

  7. POJ 2348 Euclid's Game(辗转相除博弈+自由度分析)

    题目链接:http://poj.org/problem?id=2348 题目大意:给你两个数a,b,Stan和Ollie轮流操作,每次可以将较大的数减去较小的数的整数倍,相减后结果不能小于0,谁先将其 ...

  8. free之后将指针置为NULL

    free一个指针,只是将指针指向的内存空间释放掉了,并没有将指针置为NULL,指针仍指向被释放掉的内存的地址,在判断指针是否为NULL的时候,通常是通过if(pt == NULL) ,这时,导致指针成 ...

  9. mac os版本Intellij IDEA 搭建spring mvc的maven工程(新手教学)

    由于近期换了新公司,又换mac pro作为新电脑,打算把用了很多年的eclipse换成IDEA(IDEA比eclipse的好处我就不多说了),由于mac os和IDEA刚开始用不久,所以专门用一篇博客 ...

  10. Python使用opencv

    Python配置opencv 原理 Python调用opencv的原理是:opencv编译出共享库文件,python把这个共享库文件作为一个模块加载并使用. 通俗点就是,编译opencv的时候开启py ...