30分树剖求调
查看原帖
30分树剖求调
639483
FiresonZ楼主2022/4/15 21:18

1,3,4点过了

#include<iostream>
#include<array>
#include<algorithm>
#include<vector>
#include<bitset>
using namespace std;
using gg=unsigned long long;
array<gg,500010> v;
array<gg,500010> son,fa,dep,siz;
array<gg,500010> top,dfn,rnk;
array<gg,2000010> tree,flag1;
array<vector<gg>,500010> tp;
bitset<500010> flag;
gg cnt=0,n,m,r,mod,x,y,z;
void update_need(gg l,gg r,gg k,gg nl,gg nr,gg p)
{
   	if(l<=nl&&nr<=r)
   	{
   		tree[p]+=(nr-nl+1)*k;
   		tree[p]%=mod;
   		flag1[p]+=k;
   		return;
	}
	gg mid=(nl+nr)/2;
	if(flag1[p]&&nr!=nl)
	{
		tree[p*2]+=flag1[p]*(mid-nl+1);
		tree[p*2]%=mod;
		tree[p*2+1]+=flag1[p]*(nr-mid);
		tree[p*2+1]%=mod;
		flag1[p*2]+=flag1[p];
		flag1[p*2+1]+=flag1[p];
		flag1[p]=0;
	}
	if(l<=mid)
	{
		update_need(l,r,k,nl,mid,p*2);
	}
	if(r>mid)
	{
		update_need(l,r,k,mid+1,nr,p*2+1);
	}
	tree[p]=(tree[p*2]+tree[p*2+1])%mod;
	return;
}
void build1(const gg &p)
{
	gg tpcnt=cnt;
	cnt++;
	dep[p]=dep[fa[p]]+1;
	flag[p]=true;
	for(gg i=0;i<tp[p].size();i++)
	{
		if(!flag[tp[p][i]])
		{
			fa[tp[p][i]]=p;
	    	build1(tp[p][i]);
		}
	}
	siz[p]=cnt-tpcnt;
	for(gg i=0;i<tp[p].size();i++)
	{
		if(siz[son[p]]<siz[tp[p][i]]&&fa[tp[p][i]]==p)
		{
			son[p]=tp[p][i];
		}
	}
	return;
}
void build2(const gg &p,const gg &v)
{
	cnt++;
	top[p]=v;
	dfn[p]=cnt;
	rnk[cnt]=p;
	if(!son[p])
	{
		return;
	}
	build2(son[p],v);
	for(gg i=0;i<tp[p].size();i++)
	{
		if(tp[p][i]!=son[p]&&fa[tp[p][i]]==p)
		{
			build2(tp[p][i],tp[p][i]);
		}
	}
	return;
}
void build3(const gg &l,const gg &r,const gg &p)
{
	if(l==r)
	{
		tree[p]=v[rnk[l]];
		if(tree[p]>mod)
		{
			tree[p]%=mod;
		}
		return;
	}
	gg mid=(l+r)/2;
	build3(l,mid,2*p);
	build3(mid+1,r,2*p+1);
	tree[p]=(tree[2*p]+tree[2*p+1])%mod;
	return;
}
gg checksum(const gg &l,const gg &r,const gg &ll,const gg &rr,const gg &p)
{
	if(l>=ll&&r<=rr)
	{
		return tree[p];
	}
	gg mid=(l+r)/2,tpsum=0;
	if(flag1[p])
	{
	   	tree[p*2]+=flag1[p]*(mid-ll+1);
	   	tree[p*2]%=mod;
		tree[p*2+1]+=flag1[p]*(rr-mid);
		tree[p*2+1]%=mod;
		flag1[p*2]+=flag1[p];
		flag1[p*2+1]+=flag1[p];
		flag1[p]=0;
	}
	if(ll<=mid)
	{
		tpsum+=checksum(l,mid,ll,rr,2*p);
		tpsum%=mod;
	}
	if(rr>=mid+1)
	{
		tpsum+=checksum(mid+1,r,ll,rr,2*p+1);
		tpsum%=mod;
	}
	return tpsum;
}
gg checkson(const gg &x)
{
	return checksum(1,n,dfn[x],dfn[x]+siz[x]-1,1);
}
gg checklcasum(gg x,gg y)
{
	gg sumtp=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]>dep[top[y]])
		{
			sumtp+=checksum(1,n,dfn[top[x]],dfn[x],1);
			sumtp%=mod;
			x=fa[top[x]];
		}
		else
		{
			sumtp+=checksum(1,n,dfn[top[y]],dfn[y],1);
			sumtp%=mod;
			y=fa[top[y]];
		}
	}
	if(dep[x]>dep[y])
	{
		sumtp+=checksum(1,n,dfn[y],dfn[x],1);
		sumtp%=mod;
	}
	else
	{
		sumtp+=checksum(1,n,dfn[x],dfn[y],1);
		sumtp%=mod;
	}
	return sumtp;
}
void chson(const gg &x,const gg &z)
{
	update_need(dfn[x],dfn[x]+siz[x]-1,z,1,n,1);
	return;
}
void chlca(gg x,gg y,gg z)
{
	while(top[x]!=top[y])
	{
		if(dep[top[x]]>dep[top[y]])
		{
			update_need(dfn[top[x]],dfn[x],z,1,n,1);
			x=fa[top[x]];
		}
		else
		{
			update_need(dfn[top[y]],dfn[y],z,1,n,1);
			y=fa[top[y]];
		}
	}
	if(dep[x]>dep[y])
	{
		update_need(dfn[y],dfn[x],z,1,n,1);
	}
	else
	{
		update_need(dfn[x],dfn[y],z,1,n,1);
	}
	return;
}
int main()
{
	cin>>n>>m>>r>>mod;
	for(gg i=1;i<=n;i++)
	{
		cin>>v[i];
	}
	for(gg i=1;i<=n-1;i++)
	{
		cin>>x>>y;
		tp[x].push_back(y);
		tp[y].push_back(x);
	}
	build1(r);
	cnt=0;
	build2(r,r);
	build3(1,n,1);
	for(gg i=1;i<=m;i++)
	{
		cin>>x;
		switch(x)
		{
			case 1:{
				cin>>x>>y>>z;
				chlca(x,y,z);
				break;
			}
			case 2:{
				cin>>x>>y;
				cout<<checklcasum(x,y)%mod<<'\n';
				break;
			}
			case 3:{
				cin>>x>>z;
				chson(x,z);
				break;
			}
			case 4:{
				cin>>x;
				cout<<checkson(x)%mod<<'\n';
				break;
			}
		}
	}
	return 0;
}
2022/4/15 21:18
加载中...