救救孩子,初学过不了样例
查看原帖
救救孩子,初学过不了样例
1412841
BaiBaiShaFeng楼主2024/12/19 19:30
#include <bits/stdc++.h>
#define lc k*2
#define rc k*2+1
using namespace std;
int n, m, r, p, cnt=0;
const int MN=1e5+115;
struct EDGE{
	int to, nex, beg, w;
}edge[MN];
void add_node(int x, int y){
	cnt++;
	edge[cnt].to=y;
	edge[cnt].nex=edge[x].beg;
	edge[x].beg=cnt;
	return;
}
struct STN{
	int l, r, val, tag; 
}tr[MN*4];
int wt[MN], w[MN];
int res=0;
int son[MN], id[MN], father[MN], tot, dep[MN], size[MN], top[MN];
void pushup(int k){
	tr[k].val=(tr[lc].val+tr[rc].val)%p;
	return;
}
void build(int k, int l, int r){
    tr[k].l=l; tr[k].r=r;
	if(l==r){
		tr[k].val=wt[l];
		if(tr[k].val>p){tr[k].val%=p;}
		return;
	}
	int mid=(l+r)>>1;
	build(lc,l,mid);build(rc,mid+1,r);
	pushup(k);
	return;
} 
void pushdown(int k){
	if(tr[k].tag){
		tr[lc].tag+=tr[k].tag;
		tr[rc].tag+=tr[k].tag;
		tr[lc].val+=tr[k].tag*(tr[lc].r-tr[lc].l+1);
		tr[rc].val+=tr[k].tag*(tr[rc].r-tr[rc].l+1);
		tr[lc].val%=p;
		tr[rc].val%=p;
		tr[k].tag=0;
	}

}
void update(int k, int l, int r, int v){
	if(tr[k].l>=l&&tr[k].r<=r){
		tr[k].val+=v*(tr[k].r-tr[k].l+1);
		tr[k].tag+=v;
	}else{
		pushdown(k);
		int mid=(tr[k].l+tr[k].r)>>1;
		if(mid>=l){
			update(lc,l,r,v);
		}
		if(mid<r){
			update(rc,l,r,v);
		}
		pushup(k);
	}

}
void query(int k, int l, int r){
	if(tr[k].l>=l&&tr[k].r<=r){
		res+=tr[k].val;
		res%=p;
		return;
	}
	pushdown(k);
	int mid=(tr[k].l+tr[k].r)>>1;
	if(mid>=l){
		query(lc,l,r);
	}
	if(mid<r){
		query(rc,l,r);
	}
}
void dfs1(int x, int f, int depth){
	dep[x]=depth;father[x]=f;size[x]=1;
	int bs=-1;
	for(int i=edge[x].beg;i;i=edge[i].nex){
		int y=edge[i].to;
		if(y==f){
			continue;
		}
		dfs1(y,x,depth+1);
		size[x]+=size[y];
		if(size[y]>bs){
			son[x]=y;
			bs=size[y];
		}
	}
	return;
}
void dfs2(int x, int topf){//我讨厌树链剖分呜呜呜 
	id[x]=++tot;wt[tot]=w[x];top[x]=topf;
	if(!son[x]){
		return;
	}
	dfs2(son[x],topf);
	for(int i=edge[x].beg;i;i=edge[i].nex){
		int y=edge[i].to;
		if(y==father[x]||y==son[x]){
			continue;
		}
		dfs2(y,y);
	}
	return;
}
//难绷的来了 
int Range(int x, int y){
	int ans=0;
	while(top[x]!=top[y]){//两点不同链 
		if(dep[top[x]]<dep[top[y]]){
			swap(x,y);
		}
		res=0;
		query(1,id[top[x]],id[x]);ans+=res;ans%=p;
		x=father[top[x]];//x跳到顶上 
		
	}
	//马上处就停了 
	if(dep[x]>dep[y]){
		swap(x,y);
	}
	res=0;
	query(1,id[x],id[y]);
	ans+=res;
	return ans%p;
}
void Change(int x, int y, int k){
	k%=p;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]){
			swap(x,y);
		}
		update(1,id[top[x]],id[x],k);
		x=father[top[x]];
	}
	if(dep[x]>dep[y]){
		swap(x,y);
	}
	update(1,id[x],id[y],k);
	return;
}
int Son(int x){
	res=0;
	query(1,id[x],id[x]+size[x]-1);
	return res;
}
void cSon(int x, int k){
	update(1,id[x],id[x]+size[x]-1,k);
	return;
}
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; i<=n; i++){
		int a, b;
		scanf("%d%d",&a,&b);
		add_node(a,b);
		add_node(b,a);
	}
	dfs1(r,0,1);
	dfs2(r,r);
	build(1,1,n);
	for(int i=1; i<=m; i++){
		int op;
		scanf("%d",&op);
		if(op==1){
			int a, b, c;
			scanf("%d%d%d",&a,&b,&c);
			Change(a,b,c);
		}else if(op==2){
			int a, b;
			scanf("%d%d",&a,&b);
			printf("%d\n",Range(a,b));
		}else if(op==3){
			int a, b;
			scanf("%d%d",&a,&b);
			cSon(a,b);
		}else{
			int a;
			scanf("%d",&a);
			printf("%d\n",Son(a));
		}
	}
	return 0;
}
2024/12/19 19:30
加载中...