救命,调了一下午28pts
查看原帖
救命,调了一下午28pts
594755
niweizheni楼主2024/7/10 17:25

求大佬看看错在哪里了,调了一下午 28pts #2 #3 #11 AC 其余全wa

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+15;
int n,m,r,p;

int h[N*2],to[N*2],ne[2*N],idx=1;
int a[N*2],aid[N*2];//初始值 
int sum[N*4],lazy[N*4],ll[N*4],rr[N*4];//线段树数组(和,懒标记) 
int son[N*2],id[N*2],fa[N*2],cnt=0,dep[N*2],ssize[N*2],top[N*2]; 
//son表示他的重儿子,id表示他的编号,fa表示他的父亲节点,cnt是编号记录器,dep是他的深度,ssize是他儿子加上他自己的大小,top是他重链的顶端
int ans=0,res=0;//答案 

void add(int u,int v)//链式前向星 
{
	to[idx]=v;
	ne[idx]=h[u];
	h[u]=idx++;
}




//向上累加
void push_up(int x)
{
	sum[x]=(sum[x*2]%p+sum[x*2+1]%p)%p;
}





//懒标记下放
void push_down(int x)
{
	if(lazy[x])
	{
		lazy[x*2]=lazy[x];
		lazy[x*2+1]=lazy[x];
		sum[x*2]+=lazy[x]*(rr[x*2]-ll[x*2]+1);
		sum[x*2]%=p;
		sum[x*2+1]+=lazy[x]*(rr[x*2+1]-ll[x*2+1]+1);
		sum[x*2+1]%=p;
		lazy[x]=0;
	}
}





//建立线段树
void build(int x,int l,int r)
{
	lazy[x]=0;
	ll[x]=l;
	rr[x]=r;
	if(l==r)
	{
		//cout<<aid[l]<<endl;
		sum[x]=aid[l];//如果是叶子节点就赋值回溯 
		sum[x]%=p;
		return;
	}
	int mid=(l+r)>>1;
	build(x*2,l,mid);//找左儿子 
	build(x*2+1,mid+1,r);//找右儿子 
	push_up(x);
}




//区间修改 
void update(int x,int l,int r,int k)
{
	//cout<<x<<endl;
	//cout<<l<<" "<<ll[x]<<" "<<rr[x]<<" "<<r<<" "<<x<<endl;
	if(l<=ll[x]&&rr[x]<=r)
	{
		lazy[x]+=k;
		sum[x]+=k*(rr[x]-ll[x]+1);
        sum[x]%=p;
        return;
	}
	push_down(x);
	int mid=(ll[x]+rr[x])/2;
	if(l<=mid)
	{
		update(x*2,l,r,k);
	}
	if(r>mid)
	{
		update(x*2+1,l,r,k);
	}
	push_up(x);
}




//区间查询
void query(int x,int l,int r)
{	
	//cout<<x<<endl;
	if(l<=ll[x]&&rr[x]<=r)
	{
		//cout<<sum[x]<<endl;
		res+=sum[x];
		res%=p;
		return;
	}
	push_down(x);
	int mid=(ll[x]+rr[x])>>1;
	if(l<=mid)
	{
		query(x*2,l,r);
	}
	if(r>mid)
	{
		query(x*2+1,l,r);
	}
}




//------------------------------上为线段树,下为重链剖分----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 




//第一次深搜,预处理出son,dep,fa,ssize
void dfs(int u,int f,int deep)
{
	//cout<<u<<" ";
	dep[u]=deep;//预处理dep 
	fa[u]=f;//预处理fa
	ssize[u]=1;//把自己的子树加上自己 
	int maxson=-1;
	for(int i=h[u];i!=-1;i=ne[i])//用链式前向星循环 
	{
		int v=to[i];
		if(v==f)//不能往回走,避免卡住 
		{
			continue;
		}
		dfs(v,u,deep+1);//深搜   
		ssize[u]+=ssize[v];//加上自己的儿子的子树大小(预处理ssize) 
		if(ssize[v]>maxson)
		{
			son[u]=v;//预处理son 
			maxson=ssize[v];
		}
	}
	
}




//第二次深搜,预处理id,aid,top
void dp_dfs(int u,int topf)//topf是u所在树链开始地点(顶点)
{
	//cout<<u<<" ";
	id[u]=++cnt;//记录新点编号
	aid[cnt]=a[u];//记录新点点权 
	top[u]=topf;//记录所在树链起点
	if(!son[u])
	{
		return;//没有儿子就返回 
	}
	dp_dfs(son[u],topf);//继续找重儿子 
	for(int i=h[u];i!=-1;i=ne[i])
	{
		int v=to[i];
		if(v==fa[u]||v==son[u])//判断轻儿子 
		{
			continue;
		}
		dp_dfs(v,v);//每个轻儿子都有以自己为顶点的子树 
	}
}



void updrange(int x,int y,int z)//区间修改(做和) 
{
	z%=p;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])
		{
			swap(x,y);
		}
		update(1,id[top[x]],id[x],z);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y])
	{
		swap(x,y);
	}
	update(1,id[x],id[y],z);
}




//
int qrange(int x,int y)
{
	ans=0;
	while(top[x]!=top[y])
	{
		res=0;
		if(dep[top[x]]<dep[top[y]])
		{
			swap(x,y);
		}
		query(1,id[top[x]],id[x]);
		ans+=res;
		ans%=p;
		x=fa[top[x]];
	}
	res=0;
	if(dep[x]>dep[y])
	{
		swap(x,y);
	}
	query(1,id[x],id[y]);
	ans+=res;
	ans%=p;
	return ans;
}




//更改子树值 
void upson(int x,int k)
{
	update(1,id[x],id[x]+ssize[x]-1,k);
}




//子树和相加 
int qson(int x)
{
	res=0;
	query(1,id[x],id[x]+ssize[x]-1);
	return res;
}




int main()
{
	memset(h,-1,sizeof(h));
	scanf("%d%d%d%d",&n,&m,&r,&p);
	for(int i=1;i<=n;i++)//输入每个点的点权
	{
		cin>>a[i];
		 
	}
	for(int i=1;i<n;i++)//建树 
	{
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);//使用链式前向星 
		add(y,x);
	}
	dfs(r,0,1);//执行第一次深搜,预处理出son,dep,fa,ssize
	//
	dp_dfs(r,r);//执行第二次深搜,预处理出id,top,aid
	//cout<<1;
	build(1,1,n);//建立线段树 
	for(int i=1;i<=m;i++)
	{
		int q;
		scanf("%d",&q);
		if(q==1)
		{
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			updrange(x,y,z);
		}
		else if(q==2)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			printf("%d\n",qrange(x,y));
		}
		else if(q==3)
		{
			int x,y;
			scanf("%d%d",&x,&y);
			upson(x,y);
		}
		else if(q==4)
		{
			int x;
			scanf("%d",&x);
			printf("%d\n",qson(x));
		}
	}
	return 0;
}
2024/7/10 17:25
加载中...