View on GitHub

Wenchong Huang

旧博客,文章搬迁完后删除

返回首页 返回专题

【HAOI2015】树上操作 题解

树剖裸题,可以拿来练手

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
struct Edge{int to,next;} e[200010];
int h[100010],sum=0;
int w[100010],idex[100010];
int in[100010],out[100010],dfn=0;
int hson[100010],size[100010];
int top[100010],fa[100010];

int read()
{
	int x=0,fg=1;char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-') fg=-1,ch=getchar();
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return fg*x;
}

void add_edge(int u,int v){e[++sum].to=v;e[sum].next=h[u];h[u]=sum;}

void dfs1(int u,int la)
{
	size[u]=1;int mx=0;
	for(int tmp=h[u];tmp;tmp=e[tmp].next)
	{
		int v=e[tmp].to;
		if(v==la) continue;
		fa[v]=u;dfs1(v,u);
		size[u]+=size[v];
		if(size[v]>mx) hson[u]=v;
		mx=max(mx,size[v]);
	}
}

void dfs2(int u,int tp)
{
	top[u]=tp;
	in[u]=++dfn;idex[dfn]=u;
	if(hson[u]) dfs2(hson[u],tp);
	for(int tmp=h[u];tmp;tmp=e[tmp].next)
	{
		if(e[tmp].to==fa[u]||e[tmp].to==hson[u]) continue;
		dfs2(e[tmp].to,e[tmp].to);
	}
	out[u]=dfn;
}

LL val[400010],tag[400010];

void build(int o,int l,int r)
{
	if(l==r){val[o]=w[idex[l]];return;}
	int mid=(l+r)/2;
	build(o*2,l,mid);
	build(o*2+1,mid+1,r);
	val[o]=val[o*2]+val[o*2+1];
}

void add(int o,int l,int r,int nl,int nr,LL k)
{
	if(l>=nl&&r<=nr)
	{
		val[o]+=(r-l+1)*k;
		tag[o]+=k;
		return;
	}
	int mid=(l+r)/2;
	if(nl<=mid) add(o*2,l,mid,nl,nr,k);
	if(nr>mid) add(o*2+1,mid+1,r,nl,nr,k);
	val[o]=val[o*2]+val[o*2+1]+(r-l+1)*tag[o];
}

LL query(int o,int l,int r,int nl,int nr)
{
	if(l==nl&&r==nr) return val[o];
	int mid=(l+r)/2;
	LL res=tag[o]*(nr-nl+1);
	if(nr<=mid) res+=query(o*2,l,mid,nl,nr);
	else if(nl>mid) res+=query(o*2+1,mid+1,r,nl,nr);
	else res+=query(o*2,l,mid,nl,mid)+query(o*2+1,mid+1,r,mid+1,nr);
	return res;
}

int main()
{
	int n=read(),m=read(),u,v;
	for(int i=1;i<=n;i++) w[i]=read();
	for(int i=1;i<n;i++)
	{
		u=read();v=read();
		add_edge(u,v);
		add_edge(v,u);
	}
	dfs1(1,0);
	dfs2(1,1);
	build(1,1,dfn);
	int opt,x,k;
	for(int i=1;i<=m;i++)
	{
		opt=read();x=read();
		if(opt==1)
		{
			k=read();
			add(1,1,dfn,in[x],in[x],(LL)k);
		}
		if(opt==2)
		{
			k=read();
			add(1,1,dfn,in[x],out[x],(LL)k);
		}
		if(opt==3)
		{
			LL ans=0;
			while(top[x]!=1) ans+=query(1,1,dfn,in[top[x]],in[x]),x=fa[top[x]];
			ans+=query(1,1,dfn,1,in[x]);
			printf("%lld\n",ans);
		}
	}
	return 0;
}