萌新求助树剖20pts
查看原帖
萌新求助树剖20pts
224926
让风忽悠你楼主2022/1/13 23:51
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100005
#define M 200005

using namespace std;

int n,m,r,p;
int x,y,z,ans;
int tot,cnt;
int w[N],head[N],dep[N],fa[N],size[N],son[N],idx[N],wt[N],top[N];
struct node{
	int next,to;
}e[M];
struct Tree{
	int l,r,lazy;
	int w;
	#define lson k<<1,l,mid
	#define rson k<<1|1,mid+1,r
}tree[N<<2];

inline void pushup(int k){
	tree[k].w=(tree[k<<1].w+tree[k<<1|1].w)%p;
}

inline void pushdown(int k){
	tree[k<<1].lazy+=tree[k].lazy;
	tree[k<<1|1].lazy+=tree[k].lazy;
	tree[k<<1].w=(tree[k<<1].w+tree[k].lazy*(tree[k<<1].r-tree[k<<1].l+1)%p)%p;
	tree[k<<1|1].w=(tree[k<<1|1].w+tree[k].lazy*(tree[k<<1|1].r-tree[k<<1|1].l+1)%p)%p;
	tree[k].lazy=0;
}

void build(int k,int l,int r){
	tree[k].l=l; tree[k].r=r;
	if(tree[k].l==tree[k].r){
		tree[k].w=wt[l];
		if(tree[k].w>p) tree[k].w%=p;
		return;
	}
	int mid=(tree[k].l+tree[k].r)>>1;
	build(lson);
	build(rson);
	pushup(k);
}

void change(int k){
	if(tree[k].l>=x && tree[k].r<=y){
		tree[k].w+=(tree[k].r-tree[k].l+1)*z;
		tree[k].lazy+=z;
		return;
	}
	if(tree[k].lazy) pushdown(k);
	int mid=(tree[k].r+tree[k].l)>>1;
	if(x<=mid) change(k<<1);
	if(y>mid) change(k<<1|1);
	pushup(k);
}

void query(int k){
	if(tree[k].l>=x && tree[k].r<=y){
		ans=(ans+tree[k].w)%p;
		return;
	}
	if(tree[k].lazy) pushdown(k);
	int mid=(tree[k].l+tree[k].r)>>1;
	if(x<=mid) query(k<<1);
	if(y>mid) query(k<<1|1);
}

// ------------------------------------------- 线段树 

inline void add(int u,int v){
	e[++tot].to=v;
	e[tot].next=head[u];
	head[u]=tot;
}

void dfs1(int u,int f,int deep){
	dep[u]=deep;
	fa[u]=f;
	size[u]=1;
	int maxson=-1;
	for(int i=head[u],v;i;i=e[i].next){
		v=e[i].to;
		if(v==f) continue;
		dfs1(v,u,deep+1);
		size[u]+=size[v];
		if(size[v]>maxson){
			son[u]=v;
			maxson=size[v];
		}
	}
}

void dfs2(int u,int topf){
	idx[u]=++cnt;
	wt[cnt]=w[u];
	top[u]=topf;
	if(!son[u]) return;
	dfs2(son[u],topf);
	for(int i=head[u],v;i;i=e[i].next){
		v=e[i].to;
		if(v==fa[u] || v==son[u]) continue;
		dfs2(v,v);
	}
}

// ------------------------------------------- 求dfs序 
 
inline int qrange(int u,int v){
	int res=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		ans=0;
		x=top[idx[u]]; y=idx[u];
		query(1);
		res=(res+ans)%p;
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	ans=0;
	x=idx[u]; y=idx[v];
	query(1);
	res=(res+ans)%p;
	return res;
}

inline void updrange(int u,int v){
	z%=p;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		x=top[idx[u]]; y=idx[u];
		change(1);
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	x=idx[u]; y=idx[v];
	change(1);
}

// ------------------------------------------- 

int main(){
	scanf("%d%d%d%d",&n,&m,&r,&p);
	for(int i=1;i<=n;i++)
		scanf("%d",&w[i]);
	for(int i=1,u,v;i<n;i++){
		scanf("%d%d",&u,&v);
		add(u,v);
		add(v,u);
	}
	dfs1(r,0,1);
	dfs2(r,r);
	build(1,1,n);
	int opt;
	while(m--){
		ans=0;
		scanf("%d",&opt);
		if(opt==1){
			scanf("%d%d%d",&x,&y,&z);
			updrange(x,y);
		}
		else if(opt==2){
			scanf("%d%d",&x,&y);
			printf("%d\n",qrange(x,y));
		}
		else if(opt==3){
			scanf("%d%d",&x,&z);
			y=idx[x]+size[x]-1; x=idx[x];
			change(1);
		}
		else if(opt==4){
			scanf("%d",&x);
			y=idx[x]+size[x]-1; x=idx[x];
			query(1);
			printf("%d\n",ans);
		}
	}
	return 0;
}
2022/1/13 23:51
加载中...