萌新 妹子 刚学树剖1ms,蜜汁RE
查看原帖
萌新 妹子 刚学树剖1ms,蜜汁RE
114012
chichichichi楼主2020/11/20 13:49

RT,不知哪里出了nt错误,求dalao看看

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=112345;
const int maxm=212345;
int tot,cnt;
int lin[maxn],to[maxn],ne[maxn],in[maxn];
long long m,n,a[maxn],va[maxn];//
int dfn[maxn],top[maxn];
int siz[maxn],fa[maxn];
int dep[maxn],son[maxn];
struct node{
	int l,r;
	long long s,f;
	#define l(x) c[x].l
	#define r(x) c[x].r
	#define s(x) c[x].s
	#define f(x) c[x].f
}c[maxn<<2];
void add(int u,int v)//链式前向星
{
	to[++tot]=v;
	ne[tot]=lin[u];
	lin[u]=tot;
}
---------树剖两个dfs------------
void dfs1(int s,int ff)
{
	siz[s]=1;
	int mm=-1;
	for(int i=lin[s];i;i=ne[i])
	{
		int t=to[i];
		if(t==ff)
		continue;
		dep[t]=dep[s]+1;
		fa[t]=s;
		dfs1(t,s);
		siz[s]+=siz[t];
		if(siz[t]>mm)
		{
			mm=siz[t];
			son[s]=t;
		}
	}
}
void dfs2(int s,int ff)
{
	cnt++;
	dfn[s]=cnt;
	va[cnt]=a[s];
	top[s]=ff;
	if(!son[s])
	return ;
	dfs2(son[s],ff);
	for(int i=lin[s];i;i=ne[i])
	{
		int t=to[i];
		if(t==fa[s]||t==son[s])
		continue;
		dfs2(t,t);
	}
}
---------------树剖两个dfs结束---------
------------------线段树开始-------------
void updat(int w)//更新(因为懒,所以只有一行也要写个函数)
{
	s(w)=s(w<<1)+s(w<<1|1);
	return ;
}
void spread(int w)//下放标记
{
	if(f(w))
	{
		f(w<<1)+=f(w);
		f(w<<1|1)+=f(w);
		s(w<<1)+=(f(w)*1ll*(r(w<<1)-l(w<<1)+1));
		s(w<<1|1)+=(f(w)*1ll*(r(w<<1|1)-l(w<<1|1)+1));
		f(w)=0;
	}
}
void build(int l,int r,int w)//建树
{
	l(w)=l,r(w)=r;
	if(l==r)
	{
		s(w)=va[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,w<<1);
	build(mid+1,r,w<<1|1);
	updat(w);
	return ;
}
void change(int l,int r,int k,int w)//修改
{
	if(l(w)>=l&&r(w)<=r)
	{
		s(w)+=1ll*k*(r(w)-l(w)+1);
		f(w)+=k*1ll;
		return ;
	}
	spread(w);
	int mid=(l(w)+r(w))>>1;
	if(l<=mid)
	change(l,r,k,w<<1);
	if(r>mid)
	change(l,r,k,w<<1|1);
	updat(w);
	return ;
}
long long ask(int l,int r,int w)//询问
{
	if(l(w)>=l&&r(w)<=r)
	{
		return s(w);
	}
	spread(w);
	int mid=(l(w)+r(w))>>1;
	long long ans=0;
	if(l<=mid)
	ans+=ask(l,r,w<<1);
	if(r>mid)
	ans+=ask(l,r,w<<1|1);
	return ans;
}
----------------线段树结束---------------
int main(){

	scanf("%lld%lld",&n,&m);
	
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<n;i++)
	{
		int u,b;
		scanf("%d%d",&u,&b);
		add(u,b);
		in[b]++;
	}
	int root=0;
	for(int i=1;i<=n;i++)//找根
	if(in[i]==0)
	{
		root=i;
		break;
	}
	dep[root]=1;
	dfs1(root,0);
	dfs2(root,root);
	build(1,n,1);
	for(int i=1;i<=m;i++)
	{
		int op,p,x;
		scanf("%d%d",&op,&x);
		if(op==1)
		{
			scanf("%d",&p);
			change(dfn[x],dfn[x],p,1);
		}
		if(op==2)
		{
			scanf("%d",&p);	
			change(dfn[x],dfn[x]+siz[x]-1,p,1);
		}
		if(op==3)
		{
			long long ans=0;
			int y=root;
			while(top[y]!=top[x])
			{
				if(dep[top[y]]>dep[top[x]])
				swap(x,y);
				ans+=ask(dfn[top[x]],dfn[x],1);
				x=fa[top[x]];
			}
			if(dep[x]>dep[y])
			swap(x,y);
			ans+=ask(dfn[x],dfn[y],1);
			printf("%lld\n",ans);
		}
	}
	return 0;
}
2020/11/20 13:49
加载中...