Hdu 4918 Query on the subtree(一棵树,两种操作,一种是将某个点的权值修改为v,另一种是查询距离点u不超过d的点的权值和。)
来源:互联网 发布:淘宝模特拍摄布光 编辑:程序博客网 时间:2024/06/05 10:26
传送门:Hdu 4918 Query on the subtree
题意:给出一颗n个点的树,每个点有一个权值,有两种操作,一种是将某个点的权值修改为v,另一种是查询距离点u不超过d的点的权值和。
思路:
最多有logn层的子树
对于每个点,最多属于logn个子树,那么我们可以预处理出每个点属于哪些重心以及到这些重心的距离,以每个重心建立树状数组,
每个点按照到不同重心的距离插入到不同的树状数组中,然后利用树状数组的前缀和查询到u距离不超过d的点的和假设一个重心x到u的距离为dis,那么便统计到重心x距离不超过d-dis的点的个数。但是可能两个重心之间的点是有重复的,我们还需要维护每个点的子节点的树状数组
空间复杂度:2*nlogn,时间复杂度nlognlongn
拓展:由于重心的特殊性质,还可以嵌套其他数据结构完成
#include<bits/stdc++.h>using namespace std;typedef long long ll;using namespace std;const int N=1e5+5;bool Del[N];int f[N],root,size[N],Count,idx[N],cur;int pre[N],dis[N],a[N],n;struct node{ int root,subroot,next,dis;}C[N*20];int TOT,Head[N*20];void addnode(int u,int root,int subroot,int dis){ C[TOT].root=root; C[TOT].subroot=subroot; C[TOT].next=Head[u]; C[TOT].dis=dis; Head[u]=TOT++;}struct Edge{ int to,next;}e[N*2];int tot,head[N];void init(){ tot=cur=TOT=0; memset(Head,-1,sizeof(Head)); memset(head,-1,sizeof(head));}void addedge(int u,int v){ e[tot].to=v; e[tot].next=head[u]; head[u]=tot++;}struct Tree{ int n; vector<int> T; void init(int size){ T.clear(); n=size; for(int i=0;i<=n;i++) T.push_back(0); } void add(int x,int v){ while(x<=n) T[x]+=v,x+=(x&-x); } int sum(int x){ x=min(x,n); int ret=0; while(x>0) ret+=T[x],x-=(x&-x); return ret; }}T[N*10];void getroot(int u,int pre){ f[u]=0,size[u]=1; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(v!=pre&&!Del[v]){ getroot(v,u); size[u]+=size[v],f[u]=max(f[u],size[v]); } } f[u]=max(f[u],Count-size[u]); if(f[u]<f[root]) root=u;}void getdeep(int u,int pre,int dep,int root,int subroot){ T[root].add(dep+1,a[u]); T[subroot].add(dep+1,a[u]); addnode(u,root,subroot,dep+1); for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(v==pre||Del[v]) continue; getdeep(v,u,dep+1,root,subroot); }}void dfs(int u,int pre){ size[u]=1; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(v!=pre&& !Del[v]){ dfs(v,u); size[u]+=size[v]; } }}void work(int u,int siz){ idx[u]=++cur; Del[u]=true; T[cur].init(siz+1); T[cur].add(1,a[u]); addnode(u,idx[u],0,1); dfs(u,0); for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(!Del[v]){ ++cur; T[cur].init(size[v]+1); getdeep(v,u,1,idx[u],cur); } } for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; if(!Del[v]){ f[0]=Count=size[v]; getroot(v,root=0); work(root,size[v]); } }}char s[2];int main(){ int m,u,v,x,d; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); init(); memset(Del,false,sizeof(Del)); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); addedge(u,v),addedge(v,u); } f[0]=Count=n; getroot(1,root=0); work(root,n); for(int i=1;i<=m;++i){ scanf("%s%d%d",s,&x,&d); if(s[0]=='?'){ int ans=0; for(int i=Head[x];i!=-1;i=C[i].next){ ans+=T[C[i].root].sum(d-C[i].dis+2); if(C[i].subroot) ans-=T[C[i].subroot].sum(d-C[i].dis+2); } printf("%d\n",ans); } else{ for(int i=Head[x];i!=-1;i=C[i].next){ T[C[i].root].add(C[i].dis,d-a[x]); if(C[i].subroot) T[C[i].subroot].add(C[i].dis,d-a[x]); } a[x]=d; } } } return 0;}
0 0
- Hdu 4918 Query on the subtree(一棵树,两种操作,一种是将某个点的权值修改为v,另一种是查询距离点u不超过d的点的权值和。)
- 【HDU】4918 Query on the subtree 点分治+树状数组
- HDU 1556 Color the ball 树状数组第二种:每次修改的是一个区间,所求的值是关于某个点的
- Codeforces Round #169 (Div. 2) E. Little Girl and Problem on Trees(给出一棵树,对距离某个点d范围之内的所有点+x,查询某个点的值)
- hdu 4918 Query on the subtree (动态点分治+动态开点+线段树)
- Flashback Query 查询某个时间点的数据
- HDU 4010 Query on The Trees 点权LCT
- 网上有一种错误的做法是:因为每一个双连通分量内的点low[]值都是相同的,则dfs()时,对于一条边(u,v),只需low[u]=min(low[u],low[v]),这样就不用缩点,最后求度数的时候
- ORACLE 递归查询两两之间距离最近的点
- HashSet重复标准_重复判断的问题,颜色形同,坐标点距离不超过2,则认为是同一个点对象
- 【HDU 3966 】Aragorn's Story 【树链剖分 基于点权,查询单点值,修改路径上的点权】
- 项目1——距离是一个点到另外一个点的距离
- HDU 1166 敌兵布阵(数状数组)第一种:每次修改的是一个点,所求的是关于某段区间
- 计算两平面坐标点的距离
- !HDU 4173 到点的距离不超过2.5,找最多能被满足的点的个数-简单几何
- 判断是否是凸多边形,判断点是否在多边形内,点到直线的距离
- 像素点是昂贵的
- HDU 3966 Aragorn's Story(树链剖分 (基于点权,查询单点值,修改路径的上的点权)模板题)
- 51nod 1185 威佐夫游戏 V2(威佐夫博弈)
- 96. Unique Binary Search Trees
- C++ sql的配置与基本连接
- 迁移学习和微调深度卷积神经网络
- [POJ 1743] Musical Theme (字符串哈希+二分)
- Hdu 4918 Query on the subtree(一棵树,两种操作,一种是将某个点的权值修改为v,另一种是查询距离点u不超过d的点的权值和。)
- usaco cowtour
- HDU 5718 Oracle【大数相加】
- Intellij idea run/debug 找不到配置文件
- proc文件系统
- Swing之JList的使用
- POJ 2831 Prim
- xx并发压测xx系统注册、查询、绑定邮箱等业务,数据库连接报异常及解决方法
- 【English】 8月的英语-从头,收拾旧河山