社区讨论

10pts玄关求条,孩子真的没招了!

P3384【模板】重链剖分 / 树链剖分参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mi65rg7g
此快照首次捕获于
2025/11/19 23:29
3 个月前
此快照最后确认于
2025/11/21 00:00
3 个月前
查看原帖
能想到的所有坑全填了,有神犇能调下吗
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=100001;
int n,q,tot=0,now=0,mod,root;
struct egde{
	int to,nxt;
}e[N<<1];
vector<long long>sum(N<<2),add(N<<2),v(N);
vector<int>dfn(N),rnk(N),fa(N),top(N),siz(N),dep(N),son(N),head(N);
void add1(int u,int w){
	e[++tot].to=w;
	e[tot].nxt=head[u];
	head[u]=tot;
}
int dfs1(int u,int f){
	siz[u]=1;
	int p=0;
	for(int i=head[u];i;i=e[i].nxt){
		int to=e[i].to;
		if(to==f)continue;
		fa[to]=u;
		dep[to]=dep[u]+1;
		siz[u]+=dfs1(to,u);
		if(siz[p]<siz[to])p=to;
	}
	son[u]=p;
	return siz[u];
}
void dfs2(int u,int tp){
	dfn[++now]=u;
	rnk[u]=now;
	top[u]=tp;
	int heavy=son[u];
	if(heavy!=0&&heavy!=fa[u])dfs2(heavy,tp);
	for(int i=head[u];i;i=e[i].nxt){
		int to=e[i].to;
		if(to==fa[u]||to==heavy)continue;
		dfs2(to,to);
	}
}
void build(int k,int l,int r){
	if(l==r){
		sum[k]=(1LL*v[rnk[l]]%mod+mod)%mod;
		return;
	}
	int mid=l+(r-l)/2;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	sum[k]=(sum[k<<1]+sum[k<<1|1])%mod;
}
void pushdown(int k,int l,int r){
	if(!add[k])return;
	int mid=l+(r-l)/2;
	sum[k<<1]=(sum[k<<1]+1LL*add[k]*(mid-l+1))%mod;
	add[k<<1]=(add[k<<1]+add[k])%mod;
	sum[k<<1|1]=(sum[k<<1|1]+1LL*add[k]*(r-mid))%mod;
	add[k<<1|1]=(add[k<<1|1]+add[k])%mod;
	add[k]=0;
}
void change(int k,int l,int r,int x,int y,int z){
	if(x<=l && r<=y){
		z=(1LL*z%mod+mod)%mod;
		add[k]=(add[k]+z)%mod;
		sum[k]=(sum[k]+1LL*z*(r-l+1))%mod;
		return;
	}
	pushdown(k,l,r);
	int mid=l+(r-l)/2;
	if(x<=mid)change(k<<1,l,mid,x,y,z);
	if(y>mid)change(k<<1|1,mid+1,r,x,y,z);
	sum[k]=(sum[k<<1]+sum[k<<1|1])%mod;
}
long long seek(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y)return sum[k]%mod;
	pushdown(k,l,r);
	int mid=l+(r-l)/2;
	long long res=0;
	if(x<=mid)res=(res+seek(k<<1,l,mid,x,y))%mod;
	if(y>mid)res=(res+seek(k<<1|1,mid+1,r,x,y))%mod;
	return res;
}
long long solve(int a,int b){
	long long res=0;
	while(top[a]!=top[b]){
		if(dep[top[a]]<dep[top[b]])swap(a,b);
		res=(res+seek(1,1,n,dfn[top[a]],dfn[a]))%mod;
		a=fa[top[a]];
	}
	if(dep[a]>dep[b])swap(a,b);
	res=(res+seek(1,1,n,dfn[a],dfn[b]))%mod;
	return res;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	scanf("%d%d%d%d",&n,&q,&root,&mod);
	for(int i=1;i<=n;i++){
		scanf("%lld",&v[i]);
		v[i]=(1LL*v[i]%mod+mod)%mod;
	}
	for(int i=1;i<n;i++){
		int u,w;
		scanf("%d%d",&u,&w);
		add1(u,w);
		add1(w,u);
	}
	dep[root]=1;
	fa[root]=-1;
	dfs1(root,-1);
	dfs2(root,root);
	build(1,1,n);
	while(q--){
		int opt;
		scanf("%d",&opt);
		if(opt==1){
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			while(top[x]!=top[y]){
				if(dep[top[x]]<dep[top[y]])swap(x,y);
				change(1,1,n,dfn[top[x]],dfn[x],z);
				x=fa[top[x]];
			}
			if(dep[x]>dep[y])swap(x,y);
			change(1,1,n,dfn[x],dfn[y],z);
		}
		else if(opt==2){
			int x,y;
			scanf("%d%d",&x,&y);
			printf("%lld\n",(solve(x,y)+mod)%mod);
		}
		else if(opt==3){
			int x,z;
			scanf("%d%d",&x,&z);
			change(1,1,n,dfn[x],dfn[x]+siz[x]-1,z);
		}
		else if(opt==4){
			int x;
			scanf("%d",&x);
			printf("%lld\n",(seek(1,1,n,dfn[x],dfn[x]+siz[x]-1)+mod)%mod);
		}
	}
	return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...