树剖 30pts求调 好像是取模错了,关注
查看原帖
树剖 30pts求调 好像是取模错了,关注
385817
QianK楼主2021/11/7 19:40
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 100010; 
int n;
int cnt;
int m,mod,r,x,y,z,ans,u,v,opt;
int a[maxn];
int dep[maxn],size[maxn],son[maxn],fa[maxn],top[maxn],id[maxn],wt[maxn]; 
struct node
{
	int l,r,num,tag;
};
node tree[maxn<<2];
vector <int> val[maxn];
void dfs1(int x)
{	
	size[x]=1;
	for(int i=0;i<val[x].size();i++)
	{
		int y=val[x][i];
		if(!dep[y])
		{
//			int maxson=-1;
			dep[y]=dep[x]+1;
			fa[y]=x;
			dfs1(y);
			size[x]+=size[y];
			if(size[y]>size[son[x]])
			{
//				maxson=size[y];
				son[x]=y;
			}
		}
	}
}
void dfs2(int x,int tp)
{
	top[x]=tp;
	id[x]=++cnt; 
	wt[cnt]=a[x];
	if(!son[x]) return ;
	dfs2(son[x],tp);
	for(int i=0;i<val[x].size();i++)
	{
		int y=val[x][i];
		if(y==fa[x]||y==son[x]) continue;
		dfs2(y,y);
	}
}
int ls(int x)
{
	return x<<1;
}
int rs(int x)
{
	return x<<1|1;
}
void push_up(int rt)
{
	tree[rt].num=(tree[ls(rt)].num%mod+tree[rs(rt)].num%mod)%mod;
	return ;
}
void push_down(int rt)
{
	if(tree[rt].tag)
	{
		int tg=tree[rt].tag;
		tree[ls(rt)].num+=((tree[ls(rt)].r-tree[ls(rt)].l+1)%mod)*tg%mod;
		tree[ls(rt)].tag+=tg%mod;
		tree[rs(rt)].num+=((tree[rs(rt)].r-tree[rs(rt)].l+1)%mod)*tg%mod;
		tree[rs(rt)].tag+=tg%mod;
		tree[ls(rt)].num%=mod;
		tree[rs(rt)].num%=mod;
		tree[ls(rt)].tag%=mod;
		tree[rs(rt)].tag%=mod;
		tree[rt].tag=0;
	}
}
void build(int rt,int l,int r)
{
	tree[rt].l=l;
	tree[rt].r=r;
	if(l==r)
	{
		tree[rt].num=wt[l];
		if(tree[rt].num>mod) tree[rt].num%=mod;
		return ;
	}
	int mid=(l+r)>>1;
	build(ls(rt),l,mid);
	build(rs(rt),mid+1,r);
	push_up(rt);
}
void add(int rt,int l,int r,int x)
{
	x%=mod;
	if(tree[rt].l>=l&&tree[rt].r<=r)
	{
		tree[rt].num+=((tree[rt].r-tree[rt].l+1)%mod)*x%mod;
		tree[rt].tag+=x;
		tree[rt].num%=mod;
		tree[rt].tag%=mod;
		return ;
	}
	push_down(rt);
	if(tree[ls(rt)].r>=l) add(ls(rt),l,r,x);
	if(tree[rs(rt)].l<=r) add(rs(rt),l,r,x);
	push_up(rt);
}
void search(int rt,int l,int r)
{
	if(tree[rt].l>=l&&tree[rt].r<=r)
	{
		ans+=tree[rt].num%mod;
		ans%=mod;
		return ;
	}
	push_down(rt);
	if(tree[ls(rt)].r>=l) search(ls(rt),l,r);
	if(tree[rs(rt)].l<=r) search(rs(rt),l,r);
}
void update1(int x,int y,int z)
{	
	while(top[x]!=top[y])
	{
		if(dep[x]<dep[y]) swap(x,y);
		add(1,id[top[x]],id[x],z);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	add(1,id[x],id[y],z);
}
void update2(int x,int z)
{
	add(1,id[x],id[x]+size[x]-1,z);
}
void search1(int x,int y)
{
	while(top[x]!=top[y])
	{
		if(dep[x]<dep[y]) swap(x,y);
		search(1,id[top[x]],id[x]);
		ans%=mod;
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	search(1,id[x],id[y]);
	ans%=mod;
}
void search2(int x)
{
	search(1,id[x],id[x]+size[x]-1);
	ans%=mod;
}
void debug()
{
	for(int i=1;i<=n;i++) printf("i = %d num = %d tag = %d\n",i,tree[i].num,tree[i].tag);
}
void debug2()
{
	for(int i=1;i<=n;i++) printf("i = %d id = %d son = %d w = %d\n",i,id[i],son[i],wt[i]);
}
int main()
{
//	freopen("shupou.in","r",stdin);
	scanf("%d%d%d%d",&n,&m,&r,&mod);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=n-1;i++) 
	{
		scanf("%d%d",&u,&v);
		val[u].push_back(v);
		val[v].push_back(u);  
	}
	dep[r]=1;
	dfs1(r);
	dfs2(r,r);
//	debug2();
	build(1,1,n);
//	debug();
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&opt);
		if(opt==1)
		{
			scanf("%d%d%d",&x,&y,&z);
			update1(x,y,z);
//			debug();
		}
		if(opt==2)
		{
			scanf("%d%d",&x,&y);
			ans=0;
			search1(x,y);
			ans%=mod;
			printf("%d\n",ans);
		}
		if(opt==3)
		{
			scanf("%d%d",&x,&z);
			update2(x,z);
//			debug();
		}
		if(opt==4)
		{
			scanf("%d",&x);
			ans=0;
			search2(x);
			ans%=mod;
			printf("%d\n",ans);
		}
	}
	return 0;
} 
2021/11/7 19:40
加载中...