hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)
2016-03-23 14:54
519 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:
给出一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
分析:
典型的树链剖分,对节点进行操作,可以用树状数组或者线段树。
树链剖分+树状数组:
树链剖分+线段树:
题意:
给出一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
分析:
典型的树链剖分,对节点进行操作,可以用树状数组或者线段树。
树链剖分+树状数组:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; const int maxn = 51000; struct Edge { int to,next; }edge[maxn*2]; int head[maxn],cnt,num; int a[maxn],n,m,p,c[maxn]; int size[maxn],top[maxn],id[maxn],fa[maxn],son[maxn],dep[maxn]; void init() { memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); memset(c,0,sizeof(c)); cnt=0; num=0; } void addedge(int u,int v) { edge[cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt++; } void dfs_1(int u,int f,int d) { dep[u]=d; size[u]=1; fa[u]=f; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==f) continue; dfs_1(v,u,d+1); size[u]+=size[v]; if(son[u]==-1||size[son[u]]<size[v]) son[u]=v; } } void dfs_2(int u,int tp) { top[u] = tp; id[u] = ++num; if(son[u]!=-1) dfs_2(son[u],tp); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==fa[u]||v==son[u]) continue; dfs_2(v,v); } } int lowbit(int x) { return x&-x; } int sum(int x) { int res=0; while(x>0) { res+=c[x]; x-=lowbit(x); } return res; } void add(int x,int d) { while(x<=n) { c[x]+=d; x+=lowbit(x); } } void change(int u,int v,int val) { int tp1=top[u],tp2=top[v]; while(tp1!=tp2) { if(dep[tp1]<dep[tp2]) { swap(tp1,tp2); swap(u,v); } add(id[tp1],val); add(id[u]+1,-val); u=fa[tp1]; tp1=top[u]; } if(dep[u]>dep[v]) swap(u,v); add(id[u],val); add(id[v]+1,-val); } int main() { while(~scanf("%d%d%d",&n,&m,&p)) { init(); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } dfs_1(1,0,1); dfs_2(1,1); for(int i=1;i<=n;i++) { add(id[i],a[i]); add(id[i]+1,-a[i]); } char s[5]; int c1,c2,k,c; for(int i=0;i<p;i++) { scanf("%s",s); if(s[0]=='I') { scanf("%d%d%d",&c1,&c2,&k); change(c1,c2,k); } if(s[0]=='D') { scanf("%d%d%d",&c1,&c2,&k); change(c1,c2,-k); } if(s[0]=='Q') { scanf("%d",&c); cout<<sum(id[c])<<endl; } } } return 0; }
树链剖分+线段树:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int maxn = 51000; int n,m,p; int val[maxn],a[maxn]; struct Edge { int to,next; }edge[maxn*2]; int head[maxn],add[maxn*4]; int dep[maxn],fa[maxn],size[maxn],son[maxn],top[maxn],id[maxn]; int cnt,num; void init() { memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); memset(add,0,sizeof(add)); cnt=0; num=0; } void addedge(int u,int v) { edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs_1(int u,int f,int d) { dep[u]=d; size[u]=1; fa[u]=f; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==f) continue; dfs_1(v,u,d+1); size[u]+=size[v]; if(son[u]==-1||size[son[u]]<size[v]) son[u]=v; } } void dfs_2(int u,int tp) { top[u] = tp; id[u] = ++num; if(son[u]!=-1) dfs_2(son[u],tp); for(int i=head[u];i!=-1;i=edge[i].next) { int v = edge[i].to; if(v == fa[u] ||v == son[u]) continue; dfs_2(v,v); } } struct Tree { int left,right; int sum; }tree[maxn*4]; void pushup(int i) { tree[i].sum = tree[i*2].sum + tree[i*2+1].sum; } void build(int i,int begin,int end) { tree[i].left=begin; tree[i].right=end; if(begin==end) { tree[i].sum=val[begin]; return; } int mid=(begin+end)/2; build(i*2,begin,mid); build(i*2+1,mid+1,end); pushup(i); } void pushdown(int i) { if(add[i]) { add[i*2] += add[i]; add[i*2+1] += add[i]; int mid=(tree[i].left+tree[i].right)/2; tree[i*2].sum += add[i]*(mid-tree[i].left+1); tree[i*2+1].sum += add[i]*(tree[i].right-mid); add[i]=0; } } void update(int i,int begin,int end,int value) { if(tree[i].left>=begin&&tree[i].right<=end) { add[i]+=value; tree[i].sum+=value*(tree[i].right-tree[i].left+1); return; } pushdown(i); int mid=(tree[i].left+tree[i].right)/2; if(mid>=begin) update(i*2,begin,end,value); if(mid<end) update(i*2+1,begin,end,value); pushup(i); } void change(int u,int v,int value) { int tp1=top[u],tp2=top[v]; while(tp1!=tp2) { if(dep[tp1]<dep[tp2]) { swap(tp1,tp2); swap(u,v); } update(1,id[tp1],id[u],value); u = fa[tp1]; tp1 = top[u]; } if(dep[u]>dep[v]) swap(u,v); update(1,id[u],id[v],value); } long long query(int i,int begin,int end) { if(tree[i].left>=begin&&tree[i].right<=end) return tree[i].sum; pushdown(i); int mid=(tree[i].left+tree[i].right)/2; long long ans=0; if(mid>=begin) ans+=query(i*2,begin,end); if(mid<end) ans+=query(i*2+1,begin,end); return ans; } int main() { while(~scanf("%d%d%d",&n,&m,&p)) { init(); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } dfs_1(1,0,1); dfs_2(1,1); for(int i=1;i<=n;i++) val[id[i]]=a[i]; build(1,1,n); char s[5]; int c1,c2,k,c; for(int i=0;i<p;i++) { scanf("%s",s); if(s[0]=='I') { scanf("%d%d%d",&c1,&c2,&k); change(c1,c2,k); } if(s[0]=='D') { scanf("%d%d%d",&c1,&c2,&k); change(c1,c2,-k); } if(s[0]=='Q') { scanf("%d",&c); cout<<query(1,id[c],id[c])<<endl; } } } return 0; }
相关文章推荐
- Django表单简介
- Go时间格式化和类型互换操作
- Django静态文件配置
- go on mac
- Go语言核心之美 3.2-slice切片
- lightoj 1051 - Good or Bad DP
- TypeError: unbound method func1() must be called with base1 instance as first argument (got nothing
- Django--models连表构建
- Django中的Model(表结构)
- revel nohup 部署
- Google自己的下拉刷新组件SwipeRefreshLayout
- go语言闭包,匿名函数,变量使用
- 蒙特卡罗树搜索+深度学习 -- AlphaGo原版论文阅读笔记
- Codeforces 653E:Bear and Forgotten Tree 2
- Xcode7.0无法找到category的解决方法
- Django--上传文件
- This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms whil...
- [HDU3966]Aragorn's Story 做题笔记
- 并发之痛 Thread,Goroutine,Actor
- Django--models基础