70pts #2,#9,#10 TLE
查看原帖
70pts #2,#9,#10 TLE
365532
Mr_ll楼主2022/7/20 08:05
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e5+10;

struct qwe//边 
{
	int net,to;
} E[2*maxn];

struct nod//线段树点 
{
	int sum,laz,l,r,ls,rs,le;
} nod[2*maxn];

int rt,n,m,R,P,a[maxn],cnt,hea[maxn],f[maxn],d[maxn],siz[maxn],son[maxn],rk[maxn],top[maxn],id[maxn];
int x,y,z,bs,opt;

void add(int x,int y)//邻接表 
{
	E[++bs].to=y;
	E[bs].net=hea[x];
	hea[x]=bs;
}

void push_up(int t)//上传区间和 
{
	nod[t].sum=((LL)nod[nod[t].ls].sum+(LL)nod[nod[t].rs].sum)%P;
}

void push_down(int t)//下传懒标记 
{
	if(nod[t].ls) 
	{
		nod[nod[t].ls].laz=((LL)nod[nod[t].ls].laz+(LL)nod[t].laz)%P;
		nod[nod[t].ls].sum=((LL)nod[nod[t].ls].sum+(LL)nod[nod[t].ls].le*(LL)nod[t].laz%P)%P;
		
	}
		
	if(nod[t].rs)
	{
		nod[nod[t].rs].laz=((LL)nod[nod[t].rs].laz+(LL)nod[t].laz)%P;
		nod[nod[t].rs].sum=((LL)nod[nod[t].rs].sum+(LL)nod[nod[t].rs].le*(LL)nod[t].laz%P)%P;
	}
			
	nod[t].laz=0;
}

void built(int t,int l,int r)//线段树建树 
{
	nod[t].l=l;
	nod[t].r=r;
	nod[t].le=r-l+1;
	
	if(l==r)
	{
		nod[t].sum=a[rk[l]];
		return;
	}

	int mid=(l+r)>>1;
	
	nod[t].ls=t<<1;
	built(nod[t].ls,l,mid);
	
	if(mid<r)
	{
		nod[t].rs=t<<1|1;
		built(nod[t].rs,mid+1,r);
	}
	//cout<<"biu "<<t<<' '<<nod[t].ls<<' '<<nod[t].rs<<endl;
	if(nod[t].ls||nod[t].rs) push_up(t);
}

void xadd(int t,int x,int y,int z)//线段树插入 
{
	if(nod[t].l>=x&&nod[t].r<=y)
	{
		nod[t].laz=((LL)nod[t].laz+(LL)z)%P;
		nod[t].sum=((LL)nod[t].sum+(LL)nod[t].le*(LL)z%P)%P;
		return;
	}
	
	push_down(t);
	
	if(nod[t].ls) xadd(nod[t].ls,x,y,z);
	if(nod[t].rs) xadd(nod[t].rs,x,y,z);
	
	if(nod[t].ls||nod[t].rs) push_up(t);
}

int query(int t,int x,int y)//线段树查询 
{
	int sum=0;
	
	if(nod[t].l>=x&&nod[t].r<=y)
	{
		return nod[t].sum;
	}
	
	push_down(t);
	if(nod[t].ls) sum=((LL)sum+(LL)query(nod[t].ls,x,y))%P;
	if(nod[t].rs) sum=((LL)sum+(LL)query(nod[t].rs,x,y))%P;
	if(nod[t].ls||nod[t].rs) push_up(t);
	
	return sum;
}

void dfs1(int u,int fa,int dep)//处理f,d,siz,son数组 
{
	f[u]=fa;
	d[u]=dep;
	siz[u]=1;
	for(int i=hea[u];i;i=E[i].net)
	{
		int v=E[i].to;
		if(v!=fa)
		{
			dfs1(v,u,dep+1);
			siz[u]+=siz[v];
			if(siz[v]>siz[son[u]])
			{
				son[u]=v;
			}
		}
		
	}
}

void dfs2(int u,int t)//处理top,id,rk; 
{
	top[u]=t;
	id[u]=++cnt;
	rk[cnt]=u;
	if(son[u]) dfs2(son[u],t);
	
	for(int i=hea[u];i;i=E[i].net)
	{
		int v=E[i].to;
		if(v!=son[u]&&v!=f[u])
		{
			dfs2(v,v);
		}
	} 
	return;
} 

void fadd(int x,int y,int z)//处理操作1 
{
	if(d[top[x]]<d[top[y]])
	{
		swap(x,y);
	}
	
	while(top[x]!=top[y])
	{
		xadd(rt,id[top[x]],id[x],z);
		x=f[top[x]];
		
		if(d[top[x]]<d[top[y]])
		{
			swap(x,y);
		}
		
	}
	
	if(id[x]>id[y])
	{
		swap(x,y);
	}
	xadd(rt,id[x],id[y],z);
	//cout<<"ll "<<id[x]<<' '<<id[y]<<endl;
}

int sum(int x,int y)//处理操作2 
{
	
	int ans=0;
	
	if(d[top[x]]<d[top[y]])
	{
		swap(x,y);
	}
	
	while(top[x]!=top[y])
	{
		ans=((LL)ans+(LL)query(rt,id[top[x]],id[x]))%P;
		x=f[top[x]];
		
		if(d[top[x]]<d[top[y]])
		{
			swap(x,y);
		}
		
	}
	
	if(id[x]>id[y])
	{
		swap(x,y);
	}
	ans=((LL)ans+(LL)query(rt,id[x],id[y]))%P;
	
	return ans;
}

void tadd(int x,int y)//处理操作3 
{
	xadd(rt,id[x],id[x]+siz[x]-1,y);
}

int ssum(int x)//处理操作4 
{
	return query(rt,id[x],id[x]+siz[x]-1);
}

int main()
{
	
	scanf("%d%d%d%d",&n,&m,&R,&P);
	
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	
	rt=1;
	
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	
	dfs1(R,R,1);
	dfs2(R,R);
	built(rt,1,n);
	
	for(int i=1;i<=m;i++)
	{
		scanf("%d",&opt);
		
		if(opt==1)
		{
			scanf("%d%d%d",&x,&y,&z);
			fadd(x,y,z);
		}
		
		if(opt==2)
		{
			scanf("%d%d",&x,&y);
			printf("%d\n",sum(x,y));
		}
		
		if(opt==3)
		{
			scanf("%d%d",&x,&y);
			tadd(x,y);
		}
		
		if(opt==4)
		{
			scanf("%d",&x);
			printf("%d\n",ssum(x));
		}
		
	}
	
	return 0;
}
2022/7/20 08:05
加载中...