求助!!!!!!!!!!!!!! 关于树链剖分模板 只过了一个点。。。
查看原帖
求助!!!!!!!!!!!!!! 关于树链剖分模板 只过了一个点。。。
90489
RE_Automation楼主2022/7/17 15:31
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N=1e5+7;

int n,m,rr,p;
int w[N];
vector<int>G[N];
int dep[N];
int fa[N];
int siz[N];
int hson[N];
int top[N];
int dfn[N],tot;
int rnk[N];

int T[N*4];
int lzy[N*4];
int End[N];

int x,y,z;

void dfs1(int u,int pa,int d)
{
	fa[u]=pa;
	dep[u]=d;
	siz[u]=1;
	int cnnt=0;
	hson[u]=-1;
	for(int i=0;i<G[u].size();++i)
	{
		int v=G[u][i];
		if(v==pa)continue;
		dfs1(v,u,d+1);
		siz[u]+=siz[v];
		if(siz[v]>cnnt)
		{
			cnnt=siz[v];
			hson[u]=v;
		}
	}
}

void dfs2(int u,int Top)
{
	top[u]=Top;
	dfn[u]=++tot;
	rnk[tot]=u;	
	if(hson[u]==-1)return;
	dfs2(hson[u],Top);
	End[hson[u]]=tot;
	for(int i=0;i<G[u].size();++i)
	{
		int v=G[u][i];
		if(v==fa[u]||v==hson[u])continue;
		dfs2(v,v);
		End[v]=tot;
	}
	
}

void build_tree(int u,int l,int r)
{
	if(l==r)
	{
		T[u]=w[rnk[l]]%p;
		return;
	}
	int mid=(l+r)/2;
	build_tree(u*2,l,mid);
	build_tree(u*2+1,mid+1,r);
	T[u]=(T[u*2]+T[u*2+1])%p;
}

void pushdown(int u,int l,int r,int mid)
{
	lzy[u*2]=(lzy[u*2]+lzy[u])%p;T[u*2]=(T[u*2]+(lzy[u]*(mid-l+1))%p)%p;
	lzy[u*2+1]=(lzy[u*2+1]+lzy[u])%p;T[u*2+1]=(T[u*2+1]+(lzy[u]*(r-mid))%p)%p;
	lzy[u]=0;
	return;
}

void update(int u,int l,int r,int L,int R,int pos)
{
	if(l>=L&&r<=R)
	{
		lzy[u]=(lzy[u]+pos)%p;
		T[u]=(T[u]+(pos*(r-l+1))%p)%p;
		return;
	}
	int mid=(l+r)/2;
	pushdown(u,l,r,mid);
	if(L<=mid)update(u*2,l,mid,L,R,pos);
	if(R>mid)update(u*2+1,mid+1,r,L,R,pos);
}

int query(int u,int l,int r,int L,int R)
{
	int cnt=0;
	if(l>=L&&r<=R)
	{
		cnt=(cnt+T[u])%p;
		return cnt;
	}
	int mid=(l+r)/2;
	pushdown(u,l,r,mid);
	if(L<=mid)cnt=(cnt+query(u*2,l,mid,L,R))%p;
	if(R>mid)cnt=(cnt+query(u*2+1,mid+1,r,L,R))%p;
	return cnt;
	
}

void op1()
{
	scanf("%lld%lld%lld",&x,&y,&z);
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		update(1,1,n,dfn[top[x]],dfn[x],z);
		x=fa[top[x]];
	}
	update(1,1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]),z);
	return;
}

void op2()
{
	scanf("%lld%lld",&x,&y);
	int TOT=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		TOT=(TOT+query(1,1,n,dfn[top[x]],dfn[x]))%p;
		x=fa[top[x]];
		//cout<<x<<" "<<y<<endl;
	}
	
	TOT=(TOT+query(1,1,n,min(dfn[x],dfn[y]),max(dfn[x],dfn[y])))%p;
	printf("%lld\n",TOT);
	return;
}

void op3()
{
	scanf("%lld%lld",&x,&z);
	//cout<<End[x]<<endl;
	update(1,1,n,dfn[x],End[x],z);
	return;
}

void op4()
{
	scanf("%lld",&x);
	int TOT=query(1,1,n,dfn[x],End[x])%p;
	printf("%lld\n",TOT);
	return;
}

signed main()
{
	scanf("%lld%lld%lld%lld",&n,&m,&rr,&p);
	for(int i=1;i<=n;++i)
		scanf("%lld",&w[i]);
	for(int i=1;i<n;++i)
	{
		int u,v;
		scanf("%lld%lld",&u,&v);
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs1(rr,rr,1);
	dfs2(rr,rr);
	build_tree(1,1,n);
	End[rr]=n;
	//for(int i=1;i<=n;++i)cout<<top[i]<<" ";
	//cout<<endl;
	while(m--)
	{
		int op;
		scanf("%lld",&op);
		if(op==1)op1();
		if(op==2)op2();
		if(op==3)op3();
		if(op==4)op4();
	}
	return 0;
}
2022/7/17 15:31
加载中...