30pts求助
查看原帖
30pts求助
486187
vvautedSN第一魔怔人楼主2021/7/20 22:16
#include <stdio.h>
#define Maxn 100005
//init
int N,M,R,P;
int tree[Maxn<<2],tag[Maxn<<2];//Sugment Tree
int head[Maxn<<1],to[Maxn<<1],next[Maxn<<1],cnt;//Edge
int top[Maxn],fa[Maxn],val[Maxn],dfn[Maxn],dep[Maxn],rank[Maxn],siz[Maxn],son[Maxn],dfw;//Link
//Sugment Tree
inline int lc(int p){return p<<1;}
inline int rc(int p){return p<<1|1;}
inline void push_up(int p){tree[p]=(tree[lc(p)]+tree[rc(p)])%P;}
inline void build_tree(int p,int l,int r)
{
	if(l==r)
	{
		tree[p]=val[rank[l]]%P;
		return;
	}
	int mid=(l+r)>>1;
	build_tree(lc(p),l,mid);
	build_tree(rc(p),mid+1,r);
	push_up(p);
}
inline void update_node(int p,int l,int r,int k)
{
	tree[p]=(tree[p]+(r-l+1)*k%P)%P;
	tag[p]=tag[p]+k;
	return;
}
inline void push_down(int p,int l,int r)
{
	int mid=(l+r)>>1;
	update_node(lc(p),l,mid,tag[p]);
	update_node(rc(p),mid+1,r,tag[p]);
	tag[p]=0;
}
inline void update_tree(int p,int l,int r,int ul,int ur,int k)
{
	if(ul<=l&&r<=ur)
	{
		update_node(p,l,r,k);
		return;
	}
	push_down(p,l,r);
	int mid=(l+r)>>1;
	if(mid>=ul) update_tree(lc(p),l,mid,ul,ur,k);
	if(mid<ur) update_tree(rc(p),mid+1,r,ul,ur,k);
	push_up(p);
}
inline int query_tree(int p,int l,int r,int ql,int qr)
{
	if(ql<=l&&r<=qr) return tree[p]%P; 
	push_down(p,l,r);
	int mid=(l+r)>>1;
	long long ans=0;
	if(mid>=ql) ans+=query_tree(lc(p),l,mid,ql,qr);
	if(mid+1<=qr) ans+=query_tree(rc(p),mid+1,r,ql,qr);
	return ans%P; 
} 
inline void dfs1(int p,int f)
{
	fa[p]=f;
	dep[p]=dep[f]+1;
	siz[p]=1;
	for(int i=head[p];i;i=next[i]) if(to[i]!=f)
	{
		dfs1(to[i],p);
		siz[p]+=siz[to[i]];
		if(siz[to[i]]>siz[son[p]]) son[p]=to[i];
	}
}
void dfs2(int p,int tp)
{
	dfn[p]=(++dfw);
	rank[dfw]=p;
	top[p]=tp;
	if(son[p]) dfs2(son[p],tp);
	for(int i=head[p];i;i=next[i]) if(to[i]!=fa[p]&&to[i]!=son[p])
	{
		dfs2(to[i],to[i]);
	 }  
}
inline void swap(int &a,int &b){int tmp=a;a=b;b=tmp;}
inline int q1(int u,int v)
{
	int ans=0;
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ans=(ans+query_tree(1,1,N,dfn[u],dfn[top[u]]))%P;
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	ans+=query_tree(1,1,N,dfn[u],dfn[v]);
	return ans%P;
}
inline void u1(int u,int v,int k)
{
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		update_tree(1,1,N,dfn[u],dfn[top[u]],k);
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	update_tree(1,1,N,dfn[u],dfn[v],k);
}
inline int q2(int p){return query_tree(1,1,N,dfn[p],dfn[p]+siz[p]-1);}
inline void u2(int p,int k){update_tree(1,1,N,dfn[p],dfn[p]+siz[p]-1,k);}
inline void add(int u,int v)
{
	next[++cnt]=head[u];
	to[cnt]=v;
	head[u]=cnt;
}
int main()
{
	scanf("%d%d%d%d",&N,&M,&R,&P);
	for(int i=1;i<=N;i++) scanf("%d",&val[i]);
	for(int i=1,u,v;i<N;i++) 
	{
		scanf("%d%d",&u,&v);
		add(u,v);
		add(v,u);
	}
	dfs1(R,R);
	dfs2(R,R);
	build_tree(1,1,N);
	int opt,a,b,c;
	for(int i=1;i<=M;i++)
	{
		scanf("%d",&opt);
		if(opt==1)
		{
			scanf("%d%d%d",&a,&b,&c);
			u1(a,b,c);
		}
		else if(opt==2)
		{
			scanf("%d%d",&a,&b);
			printf("%d\n",q1(a,b)%P);
		}
		else if(opt==3)
		{
			scanf("%d%d",&a,&b);
			u2(a,b);
		}
		else
		{
			scanf("%d",&a);
			printf("%d\n",q2(a));
		}
	}
}
2021/7/20 22:16
加载中...