P3178 [HAOI2015]树上操作

H y p e r l i n k Hyperlink Hyperlink

https://www.luogu.com.cn/problem/P3178


D e s c r i p t i o n Description Description

1为根,查询树上路径,单点修改和子树修改

数据范围: n ≤ 1 0 5 n\leq 10^5 n105


S o l u t i o n Solution Solution

默个板子

时间复杂度: O ( n l o g 2 n ) O(nlog^2n) O(nlog2n)


C o d e Code Code

#include 
#include
#include
#define N 100010
#define LL long long
using namespace std;int n,m,tot,l[N],fa[N],dep[N],siz[N],son[N],top[N],id[N],cnt,nv[N],x,y,opt;
struct node{int next,to;}e[N*2];
inline void add(int u,int v){e[++tot]=(node){l[u],v};l[u]=tot;return;}
LL v[N],z;
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline void dfs1(int x)
{
	siz[x]=1;
	int maxn=-1;
	for(register int i=l[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(y==fa[x]) continue;
		fa[y]=x;dep[y]=dep[x]+1;
		dfs1(y);
		siz[x]+=siz[y];
		if(siz[y]>maxn)
		{
			maxn=siz[y];
			son[x]=y;
		}
	}
	return;
}
inline void dfs2(int x,int topf)
{
	top[x]=topf;
	id[x]=++cnt;
	nv[cnt]=v[x];
	if(son[x]==0) return;
	if(son[x]) dfs2(son[x],topf);
	for(register int i=l[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(y==fa[x]||y==son[x]) continue;
		dfs2(y,y);
	}
	return;
}
struct xds
{
	#define lson k<<1
	#define rson k<<1|1
	LL sum[N<<2],lzy[N<<2];
	inline void build(int k=1,int l=1,int r=cnt)
	{
		if(l==r)
		{
			sum[k]=nv[l];
			return;
		}
		int mid=l+r>>1;
		build(lson,l,mid);build(rson,mid+1,r);
		sum[k]=sum[lson]+sum[rson];
		return;
	}
	inline void pushdown(int k,int l,int r)
	{
		if(lzy[k]==0) return;
		int mid=l+r>>1;
		lzy[lson]+=lzy[k];lzy[rson]+=lzy[k];
		sum[lson]+=lzy[k]*(mid-l+1);
		sum[rson]+=lzy[k]*(r-mid);
		lzy[k]=0;
		return;
	}
	inline void Modify(int ql,int qr,LL v,int k=1,int l=1,int r=cnt)
	{
		if(ql<=l&&r<=qr) {lzy[k]+=v;sum[k]+=(r-l+1)*v;return;}
		pushdown(k,l,r);
		int mid=l+r>>1;
		if(ql<=mid) Modify(ql,qr,v,lson,l,mid);
		if(qr>mid) Modify(ql,qr,v,rson,mid+1,r);
		sum[k]=sum[lson]+sum[rson];
		return;
	}
	 inline LL Query(int ql,int qr,int k=1,int l=1,int r=cnt) 
	 {
	 	if(ql<=l&&r<=qr) return sum[k];
	 	pushdown(k,l,r);
	 	int mid=l+r>>1;LL res=0;
	 	if(ql<=mid) res+=Query(ql,qr,lson,l,mid);
	 	if(qr>mid) res+=Query(ql,qr,rson,mid+1,r);
	 	sum[k]=sum[lson]+sum[rson];
	 	return res;
	 }
}T;
inline void gzs(int x,LL v){T.Modify(id[x],id[x]+siz[x]-1,v);return;}
inline void gdd(int x,LL v){T.Modify(id[x],id[x],v);return;}
inline LL gas(int x,int y) 
{
	LL res=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		res+=T.Query(id[top[x]],id[x]);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	res+=T.Query(id[x],id[y]);
	return res;
}
signed main()
{
	n=read();m=read();dep[1]=1;
	for(register int i=1;i<=n;i++) v[i]=read();
	for(register int i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
	dfs1(1);
	dfs2(1,1);
	T.build();
	while(m--)
	{
		opt=read();
		if(opt==1)
		{
			x=read();z=read();
			gdd(x,z);
		}
		if(opt==2)
		{
			x=read();z=read();
			gzs(x,z);
		}
		if(opt==3)
		{
			x=read();
			printf("%lld\n",gas(x,1));
		}
	}
}

你可能感兴趣的:(树链剖分)