题目链接:hdu_4918_Query on the subtree

题意:

给出一颗n个点的树,每个点有一个权值,有两种操作,一种是将某个点的权值修改为v,另一种是查询距离点u不超过d的点的权值和。

题解:

这里可以去膜膜鸟神的博客

简单来说就是对树的每个重心建立两个树状数组,然后对于每个点修改就在每个重心的BIT中去修改,查询也在每个重心的BIT中查询,然后容斥一下,就得出答案。

每种操作的复杂度为log2n,这题的细节比较多,具体看代码。

 #include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;i++)
#define pb push_back
using namespace std;
const int N=1e5+; int n,q,g[N],nxt[N*],v[N*],ed,w[N],vis[N],id[N];
int pool[*N],C_ed,pool_ed,sz[N],mi,mx[N],ROOT;
char op[]; struct node
{
int rt,subrt,dis;
node(){}
node(int _rt,int _subrt,int _dis):rt(_rt),subrt(_subrt),dis(_dis){}
}tmp;
vector<node>vt[N]; void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
void init(){ed=C_ed=pool_ed=;F(i,,n)vt[i].clear(),vis[i]=g[i]=;}
inline void up(int &a,int b){if(a<b)a=b;} struct BIT
{
int *C,n;
void init(int tot){n=tot,C=pool+pool_ed,pool_ed+=tot+;F(i,,n)C[i]=;}
inline void add(int x,int c){while(x<=n)C[x]+=c,x+=x&-x;}
inline int ask(int x,int an=)
{
if(x>n)x=n;
while(x>)an+=C[x],x-=x&-x;
return an;
}
}tr[N*]; void get_rt(int u,int fa,int num)
{
sz[u]=,mx[u]=;
for(int i=g[u];i;i=nxt[i])
if(!vis[v[i]]&&v[i]!=fa)
{
get_rt(v[i],u,num);
sz[u]+=sz[v[i]],up(mx[u],sz[v[i]]);
}
up(mx[u],num-sz[u]);
if(mx[u]<mi)ROOT=u,mi=mx[u];
} void del(int u,int fa,int rt,int subrt,int dis=)//将子树的每个点放进对应的重心
{
vt[u].pb(node(rt,subrt,dis));
tr[rt].add(dis+,w[u]);
tr[subrt].add(dis+,w[u]);
for(int i=g[u];i;i=nxt[i])
if(v[i]!=fa&&!vis[v[i]])
del(v[i],u,rt,subrt,dis+);
} void init_tree(int u=,int num=n)
{
mi=N,get_rt(u,u,num);
int rt=ROOT,rt_id=++C_ed;
tr[C_ed].init(sz[u]+);
vis[rt]=,vt[rt].pb(node(C_ed,,));
tr[C_ed].add(,w[rt]);
get_rt(rt,rt,num);//从新计算sz的大小
for(int i=g[rt];i;i=nxt[i])
if(!vis[v[i]])
{
tr[++C_ed].init(sz[v[i]]+);
del(v[i],v[i],rt_id,C_ed);
}
for(int i=g[rt];i;i=nxt[i])
if(!vis[v[i]])
init_tree(v[i],sz[v[i]]);
} int main()
{
while(~scanf("%d%d",&n,&q))
{
init();
F(i,,n)scanf("%d",w+i);
F(i,,n-)
{
int x,y;
scanf("%d%d",&x,&y);
adg(x,y),adg(y,x);
}
init_tree();
while(q--)
{
int u,v;
scanf("%s%d%d",op,&u,&v);
if(op[]=='!')
{
int size=vt[u].size(),d=v-w[u];
F(i,,size-)
{
tmp=vt[u][i];
tr[tmp.rt].add(tmp.dis+,d);//dis+1去掉距离为0在BIT上超时的BUG
if(tmp.subrt)tr[tmp.subrt].add(tmp.dis+,d);
}
w[u]+=d;
}else
{
int d=v,ans=,size=vt[u].size();
F(i,,size-)
{
tmp=vt[u][i];
ans+=tr[tmp.rt].ask(d-tmp.dis+);
if(tmp.subrt)ans-=tr[tmp.subrt].ask(d-tmp.dis+);
}
printf("%d\n",ans);
}
}
}
return ;
}

hdu_4918_Query on the subtree(树的分治+树状数组)的更多相关文章

  1. CF 293 E Close Vertices (树的分治+树状数组)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题目:给出一棵树,问有多少条路径权值和不大于w,长 ...

  2. 【bzoj3648】环套树+点分治+树状数组

    tree 1s 128M  by hzw czy神犇种了一棵树,他想知道地球的质量 给定一棵n个点的树,求树上经过点的个数≥K的路径数量ans 对于部分数据,树上某两点间会多出最多一条无向边 输入数据 ...

  3. [bzoj3155]Preprefix sum(树状数组)

    3155: Preprefix sum Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 1183  Solved: 546[Submit][Status] ...

  4. Codeforces 980E The Number Games - 贪心 - 树状数组

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...

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

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

  6. HDU4918 Query on the subtree 点分治+树状数组

    bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n. At the very begining, the i-th ...

  7. bzoj3648: 寝室管理(环套树+点分治)

    好题..写了两个半小时hh,省选的时候要一个半小时内调出这种题目还真是难= = 题目大意是给一棵树或环套树,求点距大于等于K的点对数 这里的树状数组做了一点变换.不是向上更新和向下求和,而是反过来,所 ...

  8. 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 239  Solved: 106[Submit][Status][Discuss] ...

  9. 【Bzoj 3295】 动态逆序对(树套树|CDQ分治)

    [题意] 每次删除一个数,然后问删除前逆序对数. [分析] 没有AC不开心.. 我的树状数组套字母树,应该是爆空间的,空间复杂度O(nlogn^2)啊..哭.. 然后就没有然后了,别人家的树套树是树状 ...

随机推荐

  1. Crystal Report 纵向排列,多列格式化

    一个表格区域就是一条数据,一张A4纸分布成2列4行打印. 这与通常的报表有点不一样,通常报表的明细都是一条一行:而现在要每2条放在一行,这需要用到“多列格式化”属性. 选择"多列格式”后,会 ...

  2. asp.net mvc + mysql + ef6

    1.通过NuGet包管理器安装:EntityFramework6.1.3.MySql.Data.Entity6.9.9 2.添加新建项→ADO.NET实体对象模型(命名MyContext)→空Code ...

  3. Rails 执行 rails server 报错 Could not find a JavaScript runtime

    gem install 'execj' gem install 'therubyrace' Ubuntu install Node.js(ubuntu) sudo apt-get install no ...

  4. 两句话帮你彻底记住gdb之eXamining memory

    对于刚学习Unix/Linux环境C编程的小朋友们或者写了很多所谓的C代码的老手们(其实很可能是机械程序员或者是伪程序员)来说,要记住gdb的eXaming memory的语法其实是相当不容易的,如果 ...

  5. android工具类常用方法

    1.获取手机唯一识别号 添加AndroidManifest.xml权限 <uses-permission android:name="android.permission.READ_P ...

  6. CSS3之3D效果中的transform运用

    css3中添加了很多新的标签 属性 描述 css transform 向元素应用 2D 或 3D 转换. 3 transform-origin 允许你改变被转换元素的位置. 3 transform-s ...

  7. DB2数据库实例创建与删除 学习笔记

    以root身份执行 $DB2HOME/instance/db2idrop -f 实例名,注意一定要加-f,否则不会删除实例下面sqllib文件.如果不幸忘了,执行db2icrt,会报sqllib文件存 ...

  8. RandomAccessFile类初次使用

    RandomAccessFile : java提供的对文件内容的访问 既可以读文件 也可以写文件 支持随机访问文件 可以访问文件的任意位置 (1)java文件模型 : 在硬盘上的文件是byte byt ...

  9. Ddos 攻击

    title: Ddos 防御相关 tags: Ddos, 安全, 防御 grammar_cjkRuby: true --- 防御基础 1.1. 攻击流量到底多大 谈到DDoS防御,首先就是要知道到底遭 ...

  10. c# 操作xml之xmlReader

    xmlReader的名称空间using System.Xml; xmlReader是通过流的方式来读取xml文件的内容 <?xml version="1.0" encodin ...