树剖求调
  • 板块灌水区
  • 楼主Surge_of_Force
  • 当前回复2
  • 已保存回复2
  • 发布时间2021/12/19 10:17
  • 上次更新2023/10/28 14:07:00
查看原帖
树剖求调
230875
Surge_of_Force楼主2021/12/19 10:17
#include<bits/stdc++.h>
#define ll long long
#define int long long
const int MAX=1e5+10;
using namespace std;
inline int read() {
  int fh = 1, res = 0; char ch = getchar();
  for(; !isdigit(ch); ch = getchar()) if(ch == '-') fh = -1;
  for(; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ '0');
  res = res * fh;
  return res;
}
inline void write(ll x) {
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
int p,n,ss,m;
vector<int> s[MAX];
int top[MAX],deep[MAX],son[MAX],siz[MAX],fa[MAX],bhs[MAX],bhwh[MAX],cnt;
struct xds{int l,r,w,f;}a[MAX<<2];
int ww[MAX],ans;
inline int lc(int k){return k<<1;}
inline int rc(int k){return k<<1|1;}
void dfs1(int f,int k)//树剖 
{
	deep[k]=deep[f]+1;
	fa[k]=f;
	siz[k]=1;
	for(int i=0,sizz=s[k].size();i<sizz;i++)
	{
		if(s[k][i]==f) continue;
		dfs1(k,s[k][i]);
		siz[k]+=siz[s[k][i]];
		if(siz[s[k][i]]>siz[son[k]])
			son[k]=s[k][i];
	}
	return ;
}
void dfs2(int t,int k)//树剖 
{
	top[k]=t;
	cnt++;
	bhs[k]=cnt;
	bhwh[cnt]=k;
	if(!son[k]) return ;
	dfs2(t,son[k]);
	for(int i=0,sizz=s[k].size();i<sizz;i++)
	{
		if(s[k][i]==fa[k]) continue;
		if(s[k][i]!=son[k])	dfs2(s[k][i],s[k][i]);
	}
	return ; 
}
void down(int k)//线段树Lazy_tag下传
{
	a[lc(k)].f+=a[k].f;a[rc(k)].f+=a[k].f;
	a[lc(k)].w+=a[k].f*(a[lc(k)].r-a[lc(k)].l+1);
	a[rc(k)].w+=a[k].f*(a[rc(k)].r-a[rc(k)].l+1);
	if(a[lc(k)].f>=p) a[lc(k)].f%=p;if(a[rc(k)].f>=p) a[rc(k)].f%=p;
	if(a[lc(k)].w>=p) a[lc(k)].w%=p;if(a[rc(k)].w>=p) a[rc(k)].w%=p;
	a[k].f=0;
	return ;
}
void build(int l,int r,int k)//线段树建树 
{
	a[k].l=l;a[k].r=r;
	if(l==r)
	{
		a[k].w=ww[bhwh[k]];
		if(a[k].w>=p) a[k].w%=p;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,lc(k));
	build(mid+1,r,rc(k));
	a[k].w=a[lc(k)].w+a[rc(k)].w;
	if(a[k].w>=p) a[k].w%=p;
	return ;
}
void change(int l,int r,int z,int k)//线段树修改 
{
	if(a[k].l>=l&&a[k].r<=r)
	{
		a[k].w+=z;a[k].f+=z;
		if(a[k].w>=p) a[k].w%=p;
		if(a[k].f>=p) a[k].f%=p;
		return ;
	}
	if(a[k].f) down(k);
	int mid=(a[k].l+a[k].r)>>1;
	if(l<=mid) change(l,r,z,lc(k));
	if(mid+1<=r) change(l,r,z,rc(k));
	a[k].w=a[lc(k)].w+a[rc(k)].w;
	if(a[k].w>=p) a[k].w%=p;
	return ;
}
void ask(int l,int r,int k)//线段树查询 
{
	if(a[k].l>=l&&a[k].r<=r)
	{
		ans+=a[k].w;
		if(ans>=p) ans%=p;
		return ;
	}
	if(a[k].f) down(k);
	int mid=(a[k].l+a[k].r)>>1;
	if(l<=mid) ask(l,r,lc(k));
	if(mid+1<=r) ask(l,r,rc(k));
	return ;
}
signed main()
{
	n=read();m=read();ss=read();p=read();
	for(int i=1;i<=n;i++) ww[i]=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read();
		s[x].push_back(y);
		s[y].push_back(x);
	}
	dfs1(0,ss);
	dfs2(ss,ss);
	build(1,n,1);
//	for(int i=1;i<=n;i++) cout<<bhs[bhwh[i]]<<" ";
//	cout<<endl;
	while(m--)
	{
		int opt=read();
		if(opt==1)
		{
			int x=read(),y=read(),z=read();
			while(top[x]!=top[y])
			{
				if(deep[top[x]]<deep[top[y]]) swap(x,y);
//				change(bhs[top[x]],x,z,1); 
				change(bhs[top[x]],bhs[x],z,1);
				x=fa[top[x]];
//				y=fa[top[y]];
			}
			if(deep[x]>deep[y]) swap(x,y);
			change(bhs[x],bhs[y],z,1);
		}
		if(opt==2)
		{
			ans=0;
			int x=read(),y=read();
			while(top[x]!=top[y])
			{
				if(deep[top[x]]<deep[top[y]]) swap(x,y);
				ask(bhs[top[x]],bhs[x],1); 
//				ask(bhs[top[y]],y,1);
				x=fa[top[x]];
//				y=fa[top[y]];
			}
			if(deep[x]>deep[y]) swap(x,y);
			ask(bhs[x],bhs[y],1);
			write(ans);
			putchar('\n');
		}
		if(opt==3)
		{
			int x=read(),z=read();
			change(bhs[x],bhs[x]+siz[x]-1,z,1);
		}
		if(opt==4)
		{
			ans=0;
			int x=read();
			ask(bhs[x],bhs[x]+siz[x]-1,1);
			write(ans);
			putchar('\n');
		}
	}
	return 0;
}
cpp```
2021/12/19 10:17
加载中...