树剖求调
查看原帖
树剖求调
537046
大眼仔Happy楼主2023/10/18 21:42
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
#define ll long long
ll inline read()
{
	ll num=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){num=(num<<3)+(num<<1)+(ch^48);ch=getchar();}
	return num*f;
}
int n,m,rt;ll mod,a[N],w[N];
ll add(ll x,ll y){return x+y>=mod?x+y-mod:x+y;}
ll dec(ll x,ll y){return x-y<0?x-y+mod:x-y;}
struct edge{int u,v,nxt;}e[N<<1];
int cnt,head[N];
void add(int u,int v){e[++cnt]=(edge){u,v,head[u]};head[u]=cnt;}
int tim,siz[N],fa[N],dep[N],son[N],id[N],top[N];
struct Segment_Tree
{
	ll t[N<<2],tag[N<<2];
	void up(int k){t[k]=add(t[k<<1],t[k<<1|1]);}
	void build(int k,int l,int r)
	{
		if(l==r){t[k]=a[l];return;}
		int mid=l+r>>1;
		build(k<<1,l,mid);build(k<<1|1,mid+1,r);
		up(k);
	}
	void LT(int k,int l,int r,ll v){t[k]+=1ll*(r-l+1)*v;tag[k]+=v;}
	void down(int k,int l,int r)
	{
		if(!tag[k])return;
		int mid=l+r>>1;
		LT(k<<1,l,mid,tag[k]);
		LT(k<<1|1,mid+1,r,tag[k]);
		tag[k]=0;
	}
	void upd(int k,int l,int r,int ql,int qr,ll v)
	{
		if(ql<=l&&r<=qr){LT(k,l,r,v);return;}
		down(k,l,r);
		int mid=l+r>>1;
		if(ql<=mid)upd(k<<1,l,mid,ql,qr,v);
		if(qr>mid)upd(k<<1|1,mid+1,r,ql,qr,v);
		up(k);
	}
	ll ask(int k,int l,int r,int ql,int qr)
	{
		if(ql<=l&&r<=qr)return t[k];
		down(k,l,r);
		int mid=l+r>>1;ll res=0;
		if(ql<=mid)res=add(res,ask(k<<1,l,mid,ql,qr));
		if(qr>mid)res=add(res,ask(k<<1|1,mid+1,r,ql,qr));
		return res;
	}
}Tree;
void UpdPath(int u,int v,ll w)
{
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		Tree.upd(1,1,n,id[top[u]],id[u],w);
		u=fa[top[u]];
	}
	if(dep[u]>dep[v])swap(u,v);
	Tree.upd(1,1,n,id[u],id[v],w);
}
ll AskPath(int u,int v)
{
	ll res=0;
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])swap(u,v);
		res=add(res,Tree.ask(1,1,n,id[top[u]],id[u]));
		u=fa[top[u]];
	}
	if(dep[u]>dep[v])swap(u,v);
	res=add(res,Tree.ask(1,1,n,id[u],id[v]));
	return res;
}
void UpdSubtree(int u,ll w){Tree.upd(1,1,n,id[u],id[u]+siz[u]-1,w);}
ll AskSubtree(int u){return Tree.ask(1,1,n,id[u],id[u]+siz[u]-1);}
void dfs(int u)
{
	siz[u]=1;
	for(int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].v;
		if(v==fa[u])continue;
		fa[v]=u;dep[v]=dep[u]+1;
		dfs(v);
		siz[u]+=siz[v];
		if(siz[son[u]]<siz[v])son[u]=v;
	}
}
void dfs(int u,int tid)
{
	id[u]=++tim;a[tim]=w[u];top[u]=tid;
	if(!son[u])return;
	dfs(son[u],tid);
	for(int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].v;
		if(v==fa[u]||v==son[u])continue;
		dfs(v,v);
	}
}
int main(){
	n=read();m=read();rt=read();mod=read();
	for(int i=1;i<=n;i++)w[i]=read();
	for(int i=1,u,v;i<n;i++)u=read(),v=read(),add(u,v),add(v,u);
	dep[0]=-1;dfs(rt);dfs(rt,rt);
	Tree.build(1,1,n);
	while(m--)
	{
		int op;op=read();
		if(op==1)
		{
			int x,y;ll w;
			x=read();y=read();w=read();
			UpdPath(x,y,w);
		}
		if(op==2)
		{
			int x,y;
			x=read();y=read();
			printf("%lld\n",AskPath(x,y));
		}
		if(op==3)
		{
			int x;ll w;
			x=read();w=read();
			UpdSubtree(x,w);
		}
		if(op==4)
		{
			int x;
			x=read();
			printf("%lld\n",AskSubtree(x));
		}
	}
	return 0;
}
2023/10/18 21:42
加载中...