树链剖分玄关求调
查看原帖
树链剖分玄关求调
922679
hongshixiaobai楼主2024/10/25 13:24
#include<bits/stdc++.h>
using namespace std;
int u,v,top[500005],fa[500005],hs[500005],d[500005],siz[500005],dfn[500005],cnt;
long long n,k,r,m,x,y,z,ans,lzy1[400005],a[100005];
char op;
struct xds
{
	long long v,l,r;
}t[400005];
vector<int>mp[500005];
inline void build(register long long u,register long long l,register long long r)
{
	t[u].l = l;t[u].r = r;
	if(l == r)
	{
		t[u].v = a[dfn[l]];
		t[u].v%=m;
		return;
	}
	register long long _ = l+r>>1;
	build(u<<1,l,_);build((u<<1)+1,_+1,r);
	t[u].v = (t[u<<1].v+t[(u<<1)+1].v)%m;
}
inline void upd(register long long u,register long long add)
{
	lzy1[u] = (lzy1[u]+add)%m;
	t[u].v = (t[u].v+(t[u].r-t[u].l+1)*add)%m;
}
inline void pushdown(register long long u)
{
	upd(u<<1,lzy1[u]);
	upd((u<<1)+1,lzy1[u]);
	lzy1[u] = 0;
}
inline void update(register long long u,register long long l,register long long r,register long long add)
{
    if(l>r)swap(l,r);
	if(t[u].l>=l&&t[u].r<=r)
	{
		upd(u,add);
		return;
	}
	if(t[u].l!=t[u].r)pushdown(u);
	long long _ = t[u].l+t[u].r>>1;
	if(l<=_)update(u<<1,l,r,add);
	if(r>_) update((u<<1)+1,l,r,add);
	t[u].v=(t[u<<1].v+t[(u<<1)+1].v)%m;
}
inline long long query(register long long u,register long long l,register long long r)
{
    if(l>r)swap(l,r);
	register long long v = 0;
	if(t[u].l>=l&&t[u].r<=r)return t[u].v;
	if(t[u].l!=t[u].r)pushdown(u);
	register long long _ = t[u].l+t[u].r>>1;
	if(l<=_)v+=query(u<<1,l,r);
	if(r>_) v+=query((u<<1)+1,l,r);
	t[u].v=(t[u<<1].v+t[(u<<1)+1].v)%m;
	return v%m;
}
void dfs(int u,int f)
{
	fa[u] = f;
	d[u] = d[f]+1;
	register int tmp = 0; 
	for(register int i = 0;i<mp[u].size();i++)
		if(mp[u][i]!=f)
		{
			dfs(mp[u][i],u);
			if(siz[mp[u][i]]>tmp||(siz[mp[u][i]]==tmp&&hs[u]>mp[u][i]))
			{
				tmp = siz[mp[u][i]];
				hs[u] = mp[u][i];
			}
			siz[u]+=siz[mp[u][i]];
		}
	siz[u]++;
}
void dfs1(int u,int f)
{
	dfn[u] = ++cnt;
	fa[u] = f;
	if(hs[f]!=u) top[u] = u;
	else top[u] = top[f];
	if(hs[u])dfs1(hs[u],u);
	for(register int i = 0;i<mp[u].size();i++)
		if(mp[u][i]!=f&&mp[u][i]!=hs[u])dfs1(mp[u][i],u);
}
void uplca(int x,int y,long long z)
{
	while(top[x]!=top[y])
	{
		if(d[top[x]]>d[top[y]])update(1,dfn[top[x]],dfn[x],z),x = fa[top[x]];
		else update(1,dfn[top[y]],dfn[y],z),y = fa[top[y]];
	}
	if(d[x]>=d[y])update(1,dfn[y],dfn[x],z);
	else if(d[y]>d[x])update(1,dfn[x],dfn[y],z);
}
int qlca(int x,int y)
{
	register long long res = 0;
	while(top[x]!=top[y])
	{
		if(d[top[x]]>d[top[y]]) res+=query(1,dfn[top[x]],dfn[x]),res%=m,x = fa[top[x]];
		else res+=query(1,dfn[top[y]],dfn[y]),res%=m,y = fa[top[y]];
	}
	if(d[x]>=d[y])res+=query(1,dfn[y],dfn[x]),res%=m;
	else if(d[y]>d[x])res+=query(1,dfn[x],dfn[y]),res%=m;
	return res;
}
int main()
{
	cin>>n>>k>>r>>m;
	for(register int i = 1;i<=n;i++)cin>>a[i];
	for(register int i = 1;i<n;i++)
	{
		cin>>u>>v;
		mp[u].push_back(v);
		mp[v].push_back(u);
	}
	dfs(r,r);
	dfs1(r,r);
	build(1,1,n);
	while(k--)
	{
		cin>>op;
		if(op == '1')
		{
			cin>>x>>y>>z;
			uplca(x,y,z);
		}
		else if(op == '2')
		{
			cin>>x>>y;
			ans = qlca(x,y);
			cout<<ans<<'\n';
		}
		else if(op == '3')
		{
			cin>>x>>z;
			update(1,dfn[x],dfn[x]+siz[x]-1,z);
		}
		else
		{
			cin>>x;
			ans = query(1,dfn[x],dfn[x]+siz[x]-1);
			cout<<ans<<'\n';
		}
	}
}
2024/10/25 13:24
加载中...