树链剖析板子(P3384 【模板】轻重链剖分)

对 应 对应 洛谷P3384 【模板】轻重链剖分

#include 
using namespace std;
#define GO std::ios::sync_with_stdio(false)
const int maxn=4e5+10;
int n,m,root,w[maxn],mod;
struct edge{
	int to,nxt;
}d[maxn]; int head[maxn],k=1;
void add(int u,int v){
	d[k].to=v,d[k].nxt=head[u],head[u]=k++;
}
int deep[maxn],siz[maxn],fa[maxn], son[maxn];
void dfs1(int u,int f,int depth)
{
	deep[u]=depth, fa[u]=f, siz[u]=1;
	int maxson=-1;
	for(int i=head[u];i;i=d[i].nxt)
	{
		int v=d[i].to;
		if( v==f )	continue;
		dfs1(v,u,depth+1);
		siz[u]+=siz[v];
		if(siz[v]>maxson)	maxson=siz[v],son[u]=v;
	}
}
int id[maxn],wn[maxn],top[maxn],cnt;
void dfs2(int u,int ffa)
{
	id[u]=++cnt, wn[cnt]=w[u], top[u]=ffa;
	if( son[u]==0 )	return;
	dfs2( son[u],ffa );
	for(int i=head[u];i;i=d[i].nxt)
	{
		int v=d[i].to;
		if( v==fa[u] || v==son[u] )	continue;
		dfs2(v,v);
	}
}
struct tree{
	int v,l,r,lazy;
}a[maxn];
void push_down(int p)
{
	if( !a[p].lazy )	return;
	int len1=a[p<<1].r-a[p<<1].l+1, len2=a[p<<1|1].r-a[p<<1|1].l+1;
	a[p<<1].lazy = (a[p<<1].lazy + a[p].lazy)%mod;
	a[p<<1|1].lazy = (a[p<<1|1].lazy + a[p].lazy)%mod;
	a[p<<1].v=(a[p<<1].v+a[p].lazy*len1%mod)%mod;
	a[p<<1|1].v = (a[p<<1|1].v+a[p].lazy*len2%mod)%mod;
	a[p].lazy=0;
}
void build(int p,int l,int r)
{
	a[p].l=l,a[p].r=r,a[p].lazy=0;
	if( l==r )
	{
		a[p].v=wn[l]%mod;
		return;
	}
	int mid = l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	a[p].v = (a[p<<1].v+a[p<<1|1].v)%mod;
}
void tree_add(int p,int l,int r,int k)
{
	if( l<=a[p].l&&a[p].r<=r)
	{
		a[p].v=( (a[p].r-a[p].l+1) *k+a[p].v)%mod;
		a[p].lazy=(a[p].lazy+k)%mod;
		return;
	}
	push_down(p);
	int mid=a[p].l+a[p].r>>1;
	if(l<=mid)	tree_add(p<<1,l,r,k);
	if(r>mid)	tree_add(p<<1|1,l,r,k);
	a[p].v = (a[p<<1].v+a[p<<1|1].v)%mod;
}
int tree_ask(int p,int l,int r)
{
	if( l<=a[p].l&&a[p].r<=r)	return a[p].v;
	push_down(p);
	int mid=a[p].l+a[p].r>>1,ans=0;
	if(l<=mid)	ans=(ans + tree_ask(p<<1,l,r) )%mod;
	if(r>mid)	ans=(ans + tree_ask(p<<1|1,l,r) )%mod;
	return ans;
}
void tree_addpath(int x,int y,int k)//x到y的路上加上k
{
	while(top[x] != top[y])
	{
		if( deep[ top[x] ]deep[y] )	swap(x,y);
	tree_add(1,id[x],id[y],k);
}
int tree_asksum(int x,int y)
{
 	int ans=0;
 	while( top[x]!=top[y] )
 	{
 		if( deep[ top[x] ]deep[y] )	swap(x,y);
	ans= (ans+tree_ask(1,id[x],id[y]) )%mod;
	return ans;
}
void tree_addroot(int root,int k)
{
	tree_add(1,id[root],id[root]+siz[root]-1,k);
}
int tree_askrootsum(int root)
{
	int ans=tree_ask(1,id[root],id[root]+siz[root]-1)%mod;
	return ans;
}
int main()
{
	GO;
	cin.tie(0); cout.tie(0);
	cin >> n >> m >> root >> mod;
	for(int i=1;i<=n;i++)	cin >> w[i];
	for(int i=1, l, r;i> l >> r;
		add(l,r); add(r,l);
	}
	dfs1(root,0,1);
	dfs2(root,root);
	build(1,1,n);
	for(int i=1, a1, a2, a3, a4;i<=m;i++)
	{
		cin >> a1;
		if( a1==1 )
		{
			cin >> a2 >> a3 >> a4;
			tree_addpath(a2,a3,a4%mod);
		}
		else if( a1==2 )
		{
			cin >> a2 >> a3;
			cout << tree_asksum(a2,a3) << "\n";
		}
		else if( a1==3 )
		{
			cin >> a2 >> a3;
			tree_addroot(a2,a3);
		}
		else
		{
			cin >> a2;
			cout << tree_askrootsum(a2) << "\n";
		}
	}
	return 0;
} 

你可能感兴趣的:(我的模板类)