BZOJ 4034: [HAOI2015]树上操作【树链剖分】【DFS序】
2017-10-18 19:32
405 查看
Description
有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:
操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。
题解
显然,树链剖分的序也是DFS序,直接维护就可以了。代码
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 100006 #define LL long long using namespace std; inline char nc(){ static char buf[100000],*i=buf,*j=buf; return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++; } inline LL _read(){ char ch=nc();LL sum=0,p=1; while((ch!='-')&&(!(ch>='0'&&ch<='9')))ch=nc(); if(ch=='-')p=-1,ch=nc(); while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc(); return sum*p; } struct data{ int l,r; LL sum,tag; void add(LL k){ sum+=k*(r-l+1);tag+=k; } }tree[maxn*4]; int n,T,tot,tem,top[maxn],fa[maxn],id[maxn],num[maxn],dep[maxn],H_son[maxn],lnk[maxn],son[maxn*2],nxt[maxn*2]; LL a[maxn]; bool vis[maxn]; void add(int x,int y){ nxt[++tot]=lnk[x];son[tot]=y;lnk[x]=tot; } void pushdown(int p){ if(tree[p].tag==0)return; tree[p<<1].add(tree[p].tag);tree[p<<1|1].add(tree[p].tag); tree[p].tag=0; } void build(int p,int l,int r){ tree[p].l=l;tree[p].r=r; if(l>=r)return; int mid=(l+r)>>1; build(p<<1,l,mid);build(p<<1|1,mid+1,r); } void update(int p,int l,int r,LL k){ if(tree[p].r<l||tree[p].l>r)return; if(l<=tree[p].l&&r>=tree[p].r){ tree[p].add(k);return; } pushdown(p); update(p<<1,l,r,k);update(p<<1|1,l,r,k); tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum; } LL query(int p,int l,int r){ if(tree[p].r<l||tree[p].l>r)return 0; if(l<=tree[p].l&&r>=tree[p].r)return tree[p].sum; pushdown(p); return query(p<<1,l,r)+query(p<<1|1,l,r); } void dfs1(int x){ vis[x]=0;num[x]=1; for(int j=lnk[x];j;j=nxt[j]) if(vis[son[j]]){ dep[son[j]]=dep[x]+1;fa[son[j]]=x;dfs1(son[j]); num[x]+=num[son[j]];if(num[son[j]]>num[H_son[x]])H_son[x]=son[j]; } } void dfs2(int x,int y){ vis[x]=0;top[x]=y;id[x]=++tem;update(1,tem,tem,a[x]); if(vis[H_son[x]]&&H_son[x]>0)dfs2(H_son[x],y); for(int j=lnk[x];j;j=nxt[j]) if(vis[son[j]]&&son[j]!=H_son[x])dfs2(son[j],son[j]); } LL get(int x,int y){ LL sum=0; for(;top[x]!=top[y];x=fa[top[x]]){ if(dep[top[x]]<dep[top[y]])swap(x,y); sum+=query(1,id[top[x]],id[x]); } if(id[x]>id[y])swap(x,y); return sum+query(1,id[x],id[y]); } int main(){ freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); n=_read();T=_read(); build(1,1,n); for(int i=1;i<=n;i++)a[i]=_read(); for(int i=1,x,y;i<n;i++)x=_read(),y=_read(),add(x,y),add(y,x); memset(vis,1,sizeof(vis));dfs1(1); memset(vis,1,sizeof(vis));dfs2(1,1); while(T--){ int k=_read(),x=_read(),y; if(k==1)y=_read(),update(1,id[x],id[x],y);else if(k==2)y=_read(),update(1,id[x],id[x]+num[x]-1,y);else if(k==3)printf("%lld\n",get(x,1)); } return 0; }
相关文章推荐
- [BZOJ 4034][HAOI 2015] 树上操作 树链剖分+DFS序
- 【树链剖分(DFS序)+线段树】BZOJ4034(HAOI2015)[树上操作]题解
- [树链剖分]bzoj 4034—— [HAOI2015]树上操作
- BZOJ 4034 [HAOI2015]树上操作 - 树链剖分
- 【BZOJ 4034】【HAOI 2015】树上操作【树链剖分】
- 【BZOJ4034】树上操作(HAOI2015)-树链剖分
- bzoj 4034: [HAOI2015]树上操作——树链剖分
- 【bzoj4034】【HAOI2015】【树上操作】【树链剖分】
- 【树链剖分】bzoj4034: [HAOI2015]树上操作
- |BZOJ 4034|树链剖分|线段树|[HAOI2015]树上操作
- BZOJ 4034 :[HAOI2015]树上操作 树链剖分裸题
- |BZOJ 4034|树链剖分|线段树|[HAOI2015]树上操作
- bzoj4034 [HAOI2015]树上操作(树链剖分)
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- bzoj 4034: [HAOI2015]树上操作(树链剖分+线段树区间更新)
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
- bzoj 4034: [HAOI2015]树上操作 树链剖分
- 【BZOJ4034】【HAOI2015】树上操作(树链剖分)
- BZOJ-4034: [HAOI2015]树上操作 (树链剖分 入门题 子树整体修改 线段树 区间修改+查询)
- bzoj 4034: [HAOI2015]树上操作 (树链剖分)