社区讨论

求助90分,最后一个点蜜汁WA

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

讨论操作

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

当前回复
3 条
当前快照
1 份
快照标识符
@mi7waupx
此快照首次捕获于
2025/11/21 04:40
4 个月前
此快照最后确认于
2025/11/21 04:40
4 个月前
查看原帖
CPP
#define range 1,cnt,1
#define ri register int
#define lson l,mid,u<<1
#define rson mid+1,r,u<<1|1
#define is_digit(c) ('0'<=(c) && (c)<='9')
#define morbi int l,int r,int u

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const int maxn=1e5+5;
const int inf=0x3f3f3f3f;

struct edge{
	int v,next;
}e[maxn<<1];

int ans_sum;
int n,m,root,p,cnt,ecnt;
int sum[maxn<<2],lazy[maxn<<2];
int dep[maxn],top[maxn],fa[maxn];
int seg[maxn],rev[maxn],son[maxn];
int head[maxn],num[maxn],size[maxn];

inline int read(){
	int x=0;
	char c=0;
	bool flag=false;
	while(!is_digit(c)) {flag|=c=='-';c=getchar();}
	while(is_digit(c)) {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return flag?-x:x;
}

void initialization(){
	seg[root]=1; 
	cnt=1; ecnt=0;
	top[root]=rev[1]=root;
	memset(sum,0,sizeof(sum));
	memset(lazy,0,sizeof(lazy));
	memset(size,0,sizeof(size));
	memset(head,-1,sizeof(head));
}

void adde(int u,int v){
	e[ecnt]=(edge){v,head[u]}; head[u]=ecnt++;
	e[ecnt]=(edge){u,head[v]}; head[v]=ecnt++;
}
 
void dfs1(int u,int pre){
	fa[u]=pre;
	size[u]=1;
	dep[u]=dep[pre]+1;
	for(ri i=head[u];i!=-1;i=e[i].next){
		int v=e[i].v;
		if(v==pre) continue;
		dfs1(v,u);
		size[u]=(size[u]+size[v])%p;
		if(size[v]>size[son[u]]) son[u]=v;
	}
}

void dfs2(int u,int pre){
	if(son[u]){
		seg[son[u]]=++cnt;
		top[son[u]]=top[u];
		rev[cnt]=son[u];
		dfs2(son[u],u);
	}
	for(ri i=head[u];i!=-1;i=e[i].next){
		int v=e[i].v;
		if(top[v] || v==pre) continue;
		seg[v]=++cnt; rev[cnt]=top[v]=v;
		dfs2(v,u);			 
	}
}

inline void pushup(int u){
	sum[u]=(sum[u<<1]+sum[u<<1|1])%p;
}

void pushdown(morbi){
	int mid=l+r>>1;
	
	lazy[u<<1]=(lazy[u<<1]+lazy[u])%p;
	lazy[u<<1|1]=(lazy[u<<1|1]+lazy[u])%p;
	
	sum[u<<1]=(lazy[u]*(mid-l+1)+sum[u<<1])%p;
	sum[u<<1|1]=(lazy[u]*(r-mid)+sum[u<<1|1])%p;

	lazy[u]=0;
}

void build(morbi){
	if(l==r){
		sum[u]=num[rev[l]];
		return;
	}
	int mid=l+r>>1;
	build(lson); build(rson);
	pushup(u);
}

void update(int L,int R,int x,morbi){
	if(L<=l && r<=R){
		sum[u]=(sum[u]+x*(r-l+1))%p;
		lazy[u]=(lazy[u]+x)%p;
		return;
	}
	int mid=l+r>>1;
	if(lazy[u]) pushdown(l,r,u);
	if(L<=mid) update(L,R,x,lson);
	if(R>mid)  update(L,R,x,rson);
	pushup(u);
}

int query(int L,int R,morbi){
	if(L<=l && r<=R) return sum[u]%p;
	int mid=l+r>>1,ret=0;
	if(lazy[u]) pushdown(l,r,u);
	if(L<=mid) ret=(ret+query(L,R,lson))%p;
	if(R>mid)  ret=(ret+query(L,R,rson))%p;
	return ret;
}

void change(int L,int R,int x){
	while(top[L]!=top[R]){
		if(dep[top[L]]<dep[top[R]]) swap(L,R);
		update(seg[top[L]],seg[L],x,range);
		L=fa[top[L]];
	}
	if(dep[L]>dep[R]) swap(L,R);
	update(seg[L],seg[R],x,range);
}

void getsum(int L,int R){
	ans_sum=0;
	while(top[L]!=top[R]){
		if(dep[top[L]]<dep[top[R]]) swap(L,R);
		ans_sum=(ans_sum+query(seg[top[L]],seg[L],range))%p;
		L=fa[top[L]];
	}
	if(dep[L]>dep[R]) swap(L,R);
	ans_sum=(ans_sum+query(seg[L],seg[R],range))%p;
}

int main(){
	n=read(),m=read();
	root=read(),p=read();
	
	initialization();
	
	for(ri i=1;i<=n;i++) num[i]=read()%p;
	for(ri i=1;i<n;i++) adde(read(),read());
	
	dfs1(root,0); 
	top[root]=rev[1]=root; seg[root]=1;
	dfs2(root,0); build(range);
	
	while(m--){
		int op=read(),x,y,z;
		
		if(op==1){ 
			x=read(),y=read(),z=read();
			change(x,y,z%p);
		}
		
		if(op==2){
			x=read(),y=read()%p;
			getsum(x,y);
			printf("%d\n",ans_sum);
		}
		
		if(op==3){
			x=read(),y=read();
			update(seg[x],seg[x]+size[x]-1,y%p,range);
		}
		
		if(op==4){
			x=read();
			printf("%d\n",query(seg[x],seg[x]+size[x]-1,range)%p);
		}
	}
	return 0;
}

回复

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

正在加载回复...