树链剖分,求大佬指导,10分,谢谢
查看原帖
树链剖分,求大佬指导,10分,谢谢
244597
kabout楼主2020/8/13 23:41
#include<bits/stdc++.h>
using namespace std;
int Size[100011],dep[100010],fa[100011],son[100011],tid[100011],top[100011],footmark[400011],n,m,r,p;
int cin1,cin2,cin3,cin4,t=0,st[400001],lazy[400001],num[100001]; 
vector<int>T[100001];
void pushdown(int rt,int l,int r)
{
	if(lazy[rt]&&l!=r)
	{
		int mid=l+r>>1;
		lazy[rt<<1]+=lazy[rt];
		lazy[rt<<1|1]+=lazy[rt];
		st[rt<<1]=(st[rt<<1]+(mid-l+1)*lazy[rt])%p; 
		st[rt<<1|1]=(st[rt<<1|1]+(r-mid)*lazy[rt])%p;
		lazy[rt]=0;
	}
}
void dfs(int x,int pre)
{
	dep[x]=dep[pre]+1;Size[x]=1,fa[x]=pre;
//	cout<<x<<"-"<<pre<<endl;
//	cout<<"dep: "<<dep[x]<<"-"<<dep[pre]<<endl;
	for(int i=0;i<T[x].size();i++)
	if(T[x][i]!=pre)
		{
			int v=T[x][i];
			if(v!=pre)dfs(v,x);
			Size[x]+=Size[v];
	//		cout<<"Size["<<x<<"]="<<Size[x]<<" "<<"Size["<<v<<"]="<<Size[v]<<endl;
			if(Size[son[x]]<Size[v])son[x]=v;
		}
}
void dfs2(int u,int pre,int tp)
{
	tid[u]=++t;
	footmark[t]=u;
	top[u]=tp;
	if(son[u])dfs2(son[u],u,tp);
	for(int i=0;i<T[u].size();i++)
	{
		int v=T[u][i];
		if(v!=son[u]&&v!=pre)dfs2(v,u,v);
	}
}
int creat(int rt,int l,int r)
{
	int mid=(l+r)/2;
	if(l==r)return st[rt]=num[footmark[l]];
	st[rt]=(creat(rt*2,l,mid)+creat(rt*2+1,mid+1,r))%p;
	return st[rt];
}
void add(int rt,int l,int r,int s,int e,int x)
{
//	 if(rt==2&&x==2)
	//cout<<rt<<"-"<<l<<" "<<r<<" "<<s<<" "<<e<<" "<<x<<endl; 
	if(s<=l&&r<=e) {
		lazy[rt]+=x;
		st[rt]=(st[rt]+(r-l+1)*x)%p; //******
		return;
	}
	pushdown(rt,l,r);
	int mid=(l+r)/2;
	if(s<=mid)add(rt*2,l,mid,s,e,x);	
	if(e>mid)add(rt*2+1,mid+1,r,s,e,x);
//	cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"<<endl;
	st[rt]=(st[rt<<1]+st[rt<<1|1])%p;
}
int query(int rt,int l,int r,int s,int e)
{

	if(s<=l&&r<=e)return st[rt];
	pushdown(rt,l,r);
	int ans=0,mid=(l+r)/2;	
	if(s<=mid)ans=(query(rt<<1,l,mid,s,e))%p;
	if(e>mid)ans=(ans+query(rt*2+1,mid+1,r,s,e))%p;
	return ans%p;
}
int query2(int u,int v)
{
	int l,r,ans=0;
	while(1)
	{
		if(top[u]==top[v])
		{
			l=min(tid[u],tid[v]);
			r=max(tid[v],tid[u]);
			int tmp=query(1,1,n,l,r)%p;
			return ans=(ans+tmp)%p;
		}
		else
		{
			if(dep[top[u]]<dep[top[v]])swap(u,v);
			l=tid[top[u]];
			r=tid[u];
			int tmp=query(1,1,n,l,r);
			ans=(ans+tmp)%p;
			u=fa[top[u]];
		}
	}
}
void add2(int u,int v,int x)
{
	int l,r;
	while(1)
	{
		if(top[u]==top[v])
		{
			l=min(tid[u],tid[v]);
			r=max(tid[v],tid[u]);
			add(1,1,n,l,r,x);
			return;
		}
		else
		{
			if(dep[top[u]]<dep[top[v]])swap(u,v);
			l=tid[top[u]];
			r=tid[u];
			add(1,l,n,1,r,x);
			u=fa[top[u]];			
		}
	}
}
int main(){
	cin>>n>>m>>r>>p;
	for(int i=1;i<=n;i++)
	{	
		cin>>num[i];
//		son[i]=i;
	}
	for(int i=1;i<n;i++)
	{
		cin>>cin1>>cin2;
		T[cin1].push_back(cin2);
		T[cin2].push_back(cin1);
	}
	dfs(r,r);
	dfs2(r,r,r);
	creat(1,1,n);
//	for(int i=1;i<=n;i++)cout<<"dep["<<i<<"]="<<dep[i]<<endl;
//	for(int i=1;i<=n;i++)cout<<"Size["<<i<<"]="<<Size[i]<<endl;
//	for(int i=1;i<=n;i++)cout<<"son["<<i<<"]="<<son[i]<<endl; 
//	cout<<t<<endl;
//	for(int i=1;i<=n;i++)cout<<"footmark["<<i<<"]="<<footmark[i]<<endl;
//	for(int i=1;i<=n;i++)cout<<"top["<<i<<"]="<<top[i]<<endl;
//	for(int i=1;i<=n;i++)cout<<fa[i]<<"--"<<endl;
	for(int i=1;i<=m;i++)
	{
		cin>>cin1;	
			
		if(cin1==1)
		{
			cin>>cin2>>cin3>>cin4;
			add2(cin2,cin3,cin4); //无循环 
				
		}
		else if(cin1==2)
		{
			cin>>cin2>>cin3;
			cout<<query2(cin2,cin3)%p<<endl;//死循环	
	//		cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>"<<endl;
			
		}
		else if(cin1==3)
		{
			cin>>cin2>>cin3;
			add(1,1,n,tid[cin2],tid[cin2]+Size[cin2]-1,cin3);//第二个死循环 
	//			
		}
		else
		{
			cin>>cin2;
			cout<<query(1,1,n,tid[cin2],tid[cin2]+Size[cin2]-1)%p<<endl;//
				
		}
	}	

	return 0;
}
2020/8/13 23:41
加载中...