树分治经典题+树状数组(hdu4918)
来源:互联网 发布:数据库建模工具有哪些 编辑:程序博客网 时间:2024/05/28 06:04
Query on the subtree
Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 536 Accepted Submission(s): 180
Problem Description
bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n. At the very begining, the i-th vertex is assigned with weight wi.
There are q operations. Each operations are of the following 2 types:
Change the weight of vertex v into x (denoted as "! v x"),
Ask the total weight of vertices whose distance are no more than d away from vertex v (denoted as "? v d").
Note that the distance between vertex u and v is the number of edges on the shortest path between them.
There are q operations. Each operations are of the following 2 types:
Change the weight of vertex v into x (denoted as "! v x"),
Ask the total weight of vertices whose distance are no more than d away from vertex v (denoted as "? v d").
Note that the distance between vertex u and v is the number of edges on the shortest path between them.
Input
The input consists of several tests. For each tests:
The first line contains n,q (1≤n,q≤105). The second line contains n integers w1,w2,…,wn (0≤wi≤104). Each of the following (n - 1) lines contain 2 integers ai,bidenoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following q lines contain the operations (1≤v≤n,0≤x≤104,0≤d≤n).
The first line contains n,q (1≤n,q≤105). The second line contains n integers w1,w2,…,wn (0≤wi≤104). Each of the following (n - 1) lines contain 2 integers ai,bidenoting an edge between vertices ai and bi (1≤ai,bi≤n). Each of the following q lines contain the operations (1≤v≤n,0≤x≤104,0≤d≤n).
Output
For each tests:
For each queries, a single number denotes the total weight.
For each queries, a single number denotes the total weight.
Sample Input
4 31 1 1 11 22 33 4? 2 1! 1 0? 2 13 31 2 31 21 3? 1 0? 1 1? 1 2
Sample Output
32166
Author
Xiaoxu Guo (ftiasch)
Source
2014 Multi-University Training Contest 5
题意:给定一棵树,有两种操作,1.修改某个节点的值;2.询问与某个点距离不大于d的节点的权值和是多少
思路:树分治+树状数组,树分治的过程中记录下每个节点对应的重心,他是在这个中心的哪个子树中,他距离中心的距离是多少,树状数组记录这个节点能被哪些节点更新到
树分治的关键是每个节点最多被logn个节点更新到
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=100010;const int INF=1000000000;int N,Q;int cnt,id[maxn];int w[maxn];int pool[maxn*40];//树状数组缓冲池int *tail;int tot,head[maxn];int root,Max;int size[maxn],maxv[maxn];struct BIT{ int *tree; int n; void init(int tot) { n=tot; tree=tail; tail=tail+tot; memset(tree,0,sizeof(int)*n); } void add(int x,int val) { while(x<n) { tree[x]+=val; x+=~x&x+1; } } int getsum(int x) { x=min(x,n-1); int sum=0; while(x>=0) { sum+=tree[x]; x-=~x&x+1; } return sum; }}bit[maxn<<1];int fa[maxn];int vis[maxn];struct node{ int v,next;}edge[maxn*2];;void init(){ tot=0; cnt=0; tail=pool; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis));}void add_edge(int u,int v){ edge[tot].v=v; edge[tot].next=head[u]; head[u]=tot++;}int dfssize(int u,int fa){ size[u]=1; maxv[u]=0; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==fa||vis[v])continue; dfssize(v,u); size[u]+=size[v]; if(size[v]>maxv[u])maxv[u]=size[v]; } return size[u];}void dfsroot(int r,int u,int f){ if(size[r]-size[u]>maxv[u]) maxv[u]=size[r]-size[u]; if(maxv[u]<Max)Max=maxv[u],root=u; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v==f||vis[v])continue; dfsroot(r,v,u); }}int que[maxn];int dis[maxn];struct Node{ int root,dis,subtree; Node(){} Node(int a,int b,int c):root(a),subtree(b),dis(c){}};vector<Node> V[maxn];void solve(int u,int root,int subtree){ int l,r; que[l=r=1]=u; dis[u]=1; fa[u]=0; while(l<=r) { u=que[l]; V[u].push_back(Node(id[root],subtree,dis[u])); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(vis[v]||v==fa[u])continue; dis[v]=dis[u]+1; que[++r]=v; fa[v]=u; } l++; } bit[subtree].init(r+1); for(int i=1;i<=r;i++) { int v=que[i]; bit[id[root]].add(dis[v],w[v]); bit[subtree].add(dis[v],w[v]); }}void dfs(int u){ Max=INF; int tot=0; tot=dfssize(u,0); dfsroot(u,u,0); vis[root]=1; id[root]=cnt++; V[root].push_back(Node(id[root],-1,0)); bit[id[root]].init(tot); bit[id[root]].add(0,w[root]); for(int i=head[root];i!=-1;i=edge[i].next) { int v=edge[i].v; if(vis[v])continue; solve(v,root,cnt); cnt++; } for(int i=head[root];i!=-1;i=edge[i].next) { int v=edge[i].v; if(vis[v])continue; dfs(v); }}int main(){ while(scanf("%d%d",&N,&Q)!=EOF) { int u,v; init(); for(int i=0;i<=N;i++)V[i].clear(); for(int i=1;i<=N;i++)scanf("%d",&w[i]); for(int i=1;i<N;i++) { scanf("%d%d",&u,&v); add_edge(u,v); add_edge(v,u); } dfs(1); char op[5]; int x,y; while(Q--) { scanf("%s%d%d",op,&x,&y); if(op[0]=='!') { int cha=y-w[x]; int len=V[x].size(); for(int i=0;i<len;i++) { Node tmp=V[x][i]; bit[tmp.root].add(tmp.dis,cha); if(tmp.subtree!=-1) bit[tmp.subtree].add(tmp.dis,cha);//? } w[x]+=cha; } else { int ans=0; int len=V[x].size(); for(int i=0;i<len;i++) { Node tmp=V[x][i]; ans+=bit[tmp.root].getsum(y-tmp.dis); if(tmp.subtree!=-1) ans-=bit[tmp.subtree].getsum(y-tmp.dis); } printf("%d\n",ans); } } } return 0;}
0 0
- 树分治经典题+树状数组(hdu4918)
- 【点分治】hdu4918
- 2014多校5(1008)HDU4918(点分治)
- bzoj 2683: 简单题 (CDQ分治+树状数组)
- bzoj2683 简单题 (cdq分治 + 树状数组)
- hdu 5324 Boring Class(树状数组+笛卡尔树 | 树状数组+cdq分治)
- 【bzoj2683】简单题 CDQ分治+树状数组
- HDU - 5324(分治+树状数组)
- 数据(CDQ分治+树状数组)
- BZOJ1176【CDQ分治】【树状数组】
- POJ3321 线段树,树状数组 建树经典题
- POJ 2155 Matrix (二维树状数组+经典题)
- 【BZOJ1176】【BOI2007】Mokia & 【BZOJ2683】简单题(CDQ分治+树状数组)
- poj 2299/2188 求逆序数个数(分治or线段树\树状数组)
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- hdu 5664 Lady CA and the graph (树分治,树状数组)
- HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
- HDU-4918 Query on the subtree(树分治+树状数组)
- struts2--中
- 对于Java中多线程互斥锁初步了解
- 关于重定向和转发的理解
- 初始化 赋值 拷贝
- UBUNTU配置mail发送邮件
- 树分治经典题+树状数组(hdu4918)
- WCF:如何将net.tcp协议寄宿到IIS
- 求完数
- OpenCV stereo matching BM 算法
- 欢迎使用CSDN-markdown编辑器
- 【重构】ER图生成数据库文档
- 安卓非自定义标题栏实现“返回”按钮
- [Python]基本概念与操作3(针对Python2)
- 第八周 【项目1-实现复数类中的运算符重载】3