bzoj4034 [HAOI2015]树上操作(树链剖分)
2017-09-08 09:55
316 查看
子树修改,通过dfn序可以变成区间修改。然后就是裸题了。
#include<cstdio> #include<cstring> #define ll long long #define N 100010 int n,a ,m,num=0,h ,dep ,size ,son ,fa ,top ,in ,out ,dfn=0,w ; struct edge{ int to,next; }data[N<<1]; struct node{ ll lazy,sum; }tree[N<<2]; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f; } inline int max(int x,int y){return x>y?x:y;} inline ll max(ll x,ll y){return x>y?x:y;} void dfs1(int x){ size[x]=1; for(int i=h[x];i;i=data[i].next){ int y=data[i].to; if(fa[x]==y) continue; fa[y]=x;dep[y]=dep[x]+1;dfs1(y);size[x]+=size[y]; if(size[y]>size[son[x]]) son[x]=y; } } void dfs2(int x,int tp){ top[x]=tp;in[x]=++dfn;w[dfn]=a[x]; if(son[x]) dfs2(son[x],tp); for(int i=h[x];i;i=data[i].next){ int y=data[i].to; if(y==son[x]||y==fa[x]) continue; dfs2(y,y); } out[x]=dfn; } inline void pushup(int p){ tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum; } inline void pushdown(int p,int l,int r,int mid){ if(!tree[p].lazy) return; tree[p<<1].lazy+=tree[p].lazy;tree[p<<1|1].lazy+=tree[p].lazy; tree[p<<1].sum+=(mid-l+1)*tree[p].lazy; tree[p<<1|1].sum+=(r-mid)*tree[p].lazy; tree[p].lazy=0; } void build(int p,int l,int r){ if(l==r){tree[p].sum=w[l];return;} int mid=l+r>>1; build(p<<1,l,mid);build(p<<1|1,mid+1,r); pushup(p); } void change(int p,int l,int r,int x,int y,ll v){//v也要longlong!!!坑死人。 if(x<=l&&r<=y){ tree[p].lazy+=v;tree[p].sum+=(r-l+1)*v;return; } int mid=l+r>>1;pushdown(p,l,r,mid); if(x<=mid) change(p<<1,l,mid,x,y,v); if(y>mid) change(p<<1|1,mid+1,r,x,y,v); pushup(p); } ll qsum(int p,int l,int r,int x,int y){ if(x<=l&&r<=y) return tree[p].sum; int mid=l+r>>1;pushdown(p,l,r,mid);ll sum=0; if(x<=mid) sum+=qsum(p<<1,l,mid,x,y); if(y>mid) sum+=qsum(p<<1|1,mid+1,r,x,y); return sum; } ll query(int x){ ll sum=0; while(top[x]!=1){ sum+=qsum(1,1,n,in[top[x]],in[x]); x=fa[top[x]]; } sum+=qsum(1,1,n,1,in[x]); return sum; } int main(){ // freopen("a.in","r",stdin); n=read();m=read(); for(int i=1;i<=n;++i) a[i]=read(); for(int i=1;i<n;++i){ int x=read(),y=read(); data[++num].to=y;data[num].next=h[x];h[x]=num; data[++num].to=x;data[num].next=h[y];h[y]=num; } dep[1]=1;dfs1(1);dfs2(1,1);build(1,1,n); while(m--){ int op=read(),x=read(); if(op==1) change(1,1,n,in[x],in[x],read()); if(op==2) change(1,1,n,in[x],out[x],read()); if(op==3) printf("%lld\n",query(x)); } return 0; }
相关文章推荐
- bzoj 4034: [HAOI2015]树上操作(树链剖分+线段树区间更新)
- 【bzoj4034】【HAOI2015】【树上操作】【树链剖分】
- 【BZOJ4034】【HAOI2015】树上操作(树链剖分)
- BZOJ 4034 :[HAOI2015]树上操作 树链剖分裸题
- bzoj 4034: [HAOI2015]树上操作——树链剖分
- BZOJ 4034 [HAOI2015]树上操作 树链剖分
- 【BZOJ 4034】【HAOI 2015】树上操作【树链剖分】
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- 【树链剖分】bzoj4034: [HAOI2015]树上操作
- BZOJ[4034][HAOI2015]树上操作 树链剖分+线段树
- BZOJ-4034: [HAOI2015]树上操作 (树链剖分 入门题 子树整体修改 线段树 区间修改+查询)
- bzoj 4034: [HAOI2015]树上操作 树链剖分
- 【树链剖分(DFS序)+线段树】BZOJ4034(HAOI2015)[树上操作]题解
- BZOJ 4034: [HAOI2015]树上操作【树链剖分】【DFS序】
- |BZOJ 4034|树链剖分|线段树|[HAOI2015]树上操作
- bzoj 4034: [HAOI2015]树上操作 (树链剖分)
- 【BZOJ4034】树上操作(HAOI2015)-树链剖分
- [树链剖分]bzoj 4034—— [HAOI2015]树上操作
- |BZOJ 4034|树链剖分|线段树|[HAOI2015]树上操作
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )