30分求助
查看原帖
30分求助
118630
Lube楼主2020/11/3 21:39
#include<bits/stdc++.h>
using namespace std;
int n,m,root,key,a[100005];
int head[100005],to[200005],nextt[200005],tot;
int fa[100005],sizee[100005],zson[100005],deep[100005];
int lian[100005],place[100005],top[100005],cnt;
struct s{
	long long sum,lazy;int lc,rc;
}tree[400005];
void dfs1(int mark,int last)
{
	fa[mark]=last;sizee[mark]=1;
	for(register int j=head[mark];j;j=nextt[j])
	{
		int y=to[j];if(y==last)continue;
		deep[y]=deep[mark]+1;
		dfs1(y,mark);
		sizee[mark]+=sizee[y];
		if(sizee[y]>sizee[zson[mark]])zson[mark]=y;
	}
}
void dfs2(int mark,int tp)
{
	lian[++cnt]=mark;place[mark]=cnt;top[mark]=tp;
	if(zson[mark])dfs2(zson[mark],tp);
	for(register int j=head[mark];j;j=nextt[j])
	{
		int y=to[j];if(y==fa[mark])continue;if(y==zson[mark])continue;
		dfs2(y,y);
	}
}
void pushdown(int mark)
{
	if(!tree[mark].lazy)return;
	long long num=tree[mark].lazy;
	tree[mark<<1].sum+=num*(tree[mark<<1].rc-tree[mark<<1].rc+1)%key;
	tree[mark<<1|1].sum+=num*(tree[mark<<1|1].rc-tree[mark<<1|1].lc+1)%key;
	tree[mark<<1].sum%=key;tree[mark<<1|1].sum%=key;
	tree[mark<<1].lazy+=num;tree[mark<<1|1].lazy+=num;
	tree[mark].lazy=0;
}
void build(int mark,int l,int r)
{
	tree[mark].lc=l;tree[mark].rc=r;
	if(l==r){tree[mark].sum=a[lian[l]];return;}
	int mid;mid=(l+r)>>1;
	build(mark<<1,l,mid);build(mark<<1|1,mid+1,r);
	tree[mark].sum=tree[mark<<1].sum+tree[mark<<1|1].sum;
	tree[mark].sum%=key;
}
void add(int mark,int l,int r,long long num)
{
	if(tree[mark].lc>=l&&tree[mark].rc<=r)
	{
		tree[mark].lazy+=num;tree[mark].lazy%=key;
		tree[mark].sum+=num*(tree[mark].rc-tree[mark].lc+1);
		tree[mark].sum%=key;return;
	}
	pushdown(mark);
	int mid;mid=(tree[mark].lc+tree[mark].rc)>>1;
	if(l<=mid)add(mark<<1,l,r,num);
	if(r>=mid+1)add(mark<<1|1,l,r,num);
	tree[mark].sum=tree[mark<<1].sum+tree[mark<<1|1].sum;
	tree[mark].sum%=key;
}
void change(int x,int y,long long num)
{
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		add(1,place[top[x]],place[x],num);
		x=fa[top[x]];
	}
	if(deep[x]<deep[y])swap(x,y);
	add(1,place[y],place[x],num);
}
long long findsum(int mark,int l,int r)
{
	if(tree[mark].lc>=l&&tree[mark].rc<=r)return tree[mark].sum;
	pushdown(mark);
	int mid;mid=(tree[mark].lc+tree[mark].rc)>>1;
	long long ans=0;
	if(l<=mid)ans+=findsum(mark<<1,l,r);ans%=key;
	if(mid+1<=r)ans+=findsum(mark<<1|1,l,r);
	return ans%key;
}
long long qsum(int x,int y)
{
	long long ans=0;
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]])swap(x,y);
		ans+=findsum(1,place[top[x]],place[x]);
		ans%=key;
		x=fa[top[x]];
	}
	if(deep[x]<deep[y])swap(x,y);
	ans+=findsum(1,place[y],place[x]);
	return ans%key;
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&root,&key);
	for(register int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(register int i=1;i<n;i++)
	{
		int g1,g2;scanf("%d%d",&g1,&g2);
		to[++tot]=g2;nextt[tot]=head[g1];head[g1]=tot;
		to[++tot]=g1;nextt[tot]=head[g2];head[g2]=tot;
	}
	dfs1(root,root);dfs2(root,root);build(1,1,n);
	for(register int i=1;i<=m;i++)
	{
		int op;
		scanf("%d",&op);
		if(op==1)
		{
			int x,y;long long z;scanf("%d%d%lld",&x,&y,&z);
			change(x,y,z);
		}
		if(op==2)
		{
			int x,y;scanf("%d%d",&x,&y);
			printf("%lld\n",qsum(x,y));
		}
		if(op==3)
		{
			int x;long long y;scanf("%d%lld",&x,&y);
			add(1,place[x],place[x]+sizee[x]-1,y);
		}
		if(op==4)
		{
			int x;scanf("%d",&x);
			printf("%lld\n",findsum(1,place[x],place[x]+sizee[x]-1));
		}
	}
}
2020/11/3 21:39
加载中...