P3178 [HAOI2015]树上操作

操作 1 :把某个节点 x 的点权增加 a 。
操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。
操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

树剖板子

const int N=1e5+79;
int a[N],b[N];
int n,m;

struct graph{
	int head[N],tot,next[N<<1],ver[N<<1];
	inline void add(int a,int b){
		ver[++tot]=b;
		next[tot]=head[a];
		head[a]=tot;
	}
}G;
int top[N],dep[N],fa[N],son[N],siz[N],dfn[N],tim;
inline void dfs1(int x){
	siz[x]=1;
	dep[x]=dep[fa[x]]+1;
	repg(x){
		int y(G.ver[i]);
		if(y==fa[x]) continue;
		fa[y]=x;
		dfs1(y);
		siz[x]+=siz[y];
		if(siz[son[x]]<siz[y]){
			son[x]=y;
		}
	}
}
inline void dfs2(int x,int topf){
	dfn[x]=++tim;
	b[tim]=a[x];
	top[x]=topf;
	if(son[x]){
		dfs2(son[x],topf);
	}
	repg(x){
		int y(G.ver[i]);
		if(y==son[x]||y==fa[x]) continue;
		dfs2(y,y);
	}
}

struct SegmentTree{
	int lc[N<<2],rc[N<<2];
	lxl sum[N<<2],tag[N<<2];
	int cnt,rt;
	inline void pushup(int p){
		sum[p]=sum[lc[p]]+sum[rc[p]];
	}
	inline void pushdown(int &p,int L,int R){
		if(!tag[p]) return ;
		int mid(L+R>>1);
		if(lc[p]){
			sum[lc[p]]+=(mid-L+1)*tag[p];
			tag[lc[p]]+=tag[p];
		}
		if(rc[p]){
			sum[rc[p]]+=(R-mid)*tag[p];
			tag[rc[p]]+=tag[p];
		}
		tag[p]=0;
	}
	inline void build(int &p,int L,int R){
		if(!p) p=++cnt;
		if(L==R){
			sum[p]=b[L];
			return ;
		}
		int mid(L+R>>1);
		build(lc[p],L,mid);
		build(rc[p],mid+1,R);
		pushup(p);
	}
	inline void change(int &p,int L,int R,int ll,int rr,lxl val){
		if(!p) p=++cnt;
		if(ll<=L&&rr>=R){
			sum[p]+=(R-L+1)*val;
			tag[p]+=val;
			return;
		}
		pushdown(p,L,R);
		int mid(L+R>>1);
		if(ll<=mid) change(lc[p],L,mid,ll,rr,val);
		if(rr>mid) change(rc[p],mid+1,R,ll,rr,val);
		pushup(p);
	}inline lxl query(int &p,int L,int R,int ll,int rr){
		if(!p) return 0;
		
		if(ll<=L&&rr>=R){
			return sum[p];
		}
		pushdown(p,L,R);
		int mid(L+R>>1);
		lxl ans(0);
		if(ll<=mid) ans+=query(lc[p],L,mid,ll,rr);
		if(rr>mid) ans+=query(rc[p],mid+1,R,ll,rr);
		return ans;
	}
}S;
inline lxl Qchain(int x,int y){
	lxl ans(0);
	while(top[x]^top[y]){
		if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
		ans+=S.query(S.rt,1,n,dfn[top[x]],dfn[x]);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) std::swap(x,y);
	ans+=S.query(S.rt,1,n,dfn[x],dfn[y]);
	return ans;
}
/*
5 1
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
*/
int main(){
	read(n);read(m);
	rep(i,1,n){
		read(a[i]);
	}
	int a,y;
    rep(i,2,n){
    	read(a);read(y);
    	G.add(a,y);
    	G.add(y,a);
	}
	
	dfs1(1);
	
	dfs2(1,1);
	S.build(S.rt,1,n);
	
	
	int op,x;
	rep(i,1,m){
		read(op);
		if(op==1){
			read(x);read(a);
			S.change(S.rt,1,n,dfn[x],dfn[x],a);
		}else if(op==2){
				read(x);read(a);
			S.change(S.rt,1,n,dfn[x],dfn[x]+siz[x]-1,a);
		}else {
			read(x);
			out(Qchain(1,x),'\n');
		}
	}
	return 0;
}
上一篇:并查集习题X-Plosives(uvaOJ1160)


下一篇:并查集