题目链接: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. eclipse集成配置JDK和Tomcat

    在eclipse中集成JDK和tomcat服务器方法很简单,我们可以在服务器上运行想要的东西.比如我们学习javaweb时就要用到. 工具/原料   eclipse,JDK,tomcat 方法/步骤 ...

  2. 如何得到AdoConnection.execute(sqlstr)执行的返回结果

    如何得到AdoConnection.execute(sqlstr)执行的返回结果? 1: TAdoConnection.execute有procedure.function的两种定义,function ...

  3. sequekize

    关于sequelize的准备工作这里不再赘述. 一.引入sequelize模块 var Sequelize = require('sequelize'); 二.连接数据库 var sequelize  ...

  4. c# PictureBox 的图像上使用鼠标画矩形框

    C# 中在图像上画框,通过鼠标来实现主要有四个消息响应函数MouseDown, MouseMove, MouseUp, Paint重绘函数实现.当鼠标键按下时开始画框,鼠标键抬起时画框结束. Poin ...

  5. nginx如何配置网页错误页面

    首先要在http模块中加入 fastcgi_intercept_errors on; 其次要在server模块中加入 error_page 403 404 /40x.html; location = ...

  6. JTable,TableModel,DefaultTableModel与AbstractTableModel的小结

    1 表格JTable并不存储自己的数据,而是从表格模型那里获取它的数据 2 TableModel本身是一个interface,在这个interface里面定义了若干的方法,包括了存取表格字段(cell ...

  7. Servle资源注射

    Servle资源注射@WebServlet(name = "DownloadServlet",urlPatterns ="/DownloadServlet" ) ...

  8. 浅谈javascript中stopImmediatePropagation函数和stopPropagation函数的区别

    在事件处理程序中,每个事件处理程序中间都会有一个event对象,而这个event对象有两个方法,一个是stopPropagation方法,一个是stopImmediatePropagation方法,两 ...

  9. JS---控制键盘事件

    键盘事件汇总: 1.onkeydown 键盘按下时触发; 2.onkeyup  键盘按下后抬起触发的事件  3.onkeypress 这个事件在用户按下并放开任何字母数字键时发生(不常用) keyCo ...

  10. c# 操作xml之xmlReader

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