社区讨论

看在你老婆亚丝娜的份上帮小舅子一把

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

讨论操作

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

当前回复
2 条
当前快照
1 份
快照标识符
@mi6vafel
此快照首次捕获于
2025/11/20 11:24
4 个月前
此快照最后确认于
2025/11/20 11:24
4 个月前
查看原帖
蜜汁wa了2,9,10,%过了,longlong也开了,数组也够大,请问是什么问题? 拜托了
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
struct Way{
	int to,next;
} way[N<<1];
int n,m,r,flag,cnt,t,head[N];
int num,fa[N],dep[N],size[N],son[N],top[N],dfn[N],rev[N];
long long p,a,b,c,first[N],lazy[N],tree[N<<2],val[N];
void addway(int u,int v){
	way[++cnt].to=v;
	way[cnt].next=head[u];
	head[u]=cnt;
}
void dfs1(int cur,int f,int d){
	fa[cur]=f; dep[cur]=d; size[cur]=1;
	int maxx=-1;
	for(int i=head[cur];i;i=way[i].next){
		if(way[i].to==f) continue;
		dfs1(way[i].to,cur,d+1);
		size[cur]+=size[way[i].to];
		if(size[way[i].to]>maxx) {
			maxx=size[way[i].to]; son[cur]=way[i].to;
		}
	}
}
void dfs2(int cur,int topf){
	top[cur]=topf; dfn[cur]=++t; rev[t]=cur; first[t]=val[cur];
	if(!son[cur]) return;
	dfs2(son[cur],topf);
	for(int i=head[cur];i;i=way[i].next){
		if(way[i].to==fa[cur]||way[i].to==son[cur]) continue;
		dfs2(way[i].to,way[i].to);
	}
}
void pushdown(int o,int l,int r,int mid){
	tree[o<<1]=(tree[o<<1]+lazy[o]*(mid-l+1)%p)%p;
	lazy[o<<1]=(lazy[o<<1]+lazy[o]%p)%p;
	tree[o<<1|1]=(tree[o<<1|1]+lazy[o]*(r-mid)%p)%p;
	lazy[o<<1|1]=(lazy[o<<1|1]+lazy[o]%p)%p;
	lazy[o]=0;
}
void maketree(int o,int l,int r){
	if(l==r){
		tree[o]=first[l]%p; return;
	}
	int mid=l+r>>1;
	maketree(o<<1,l,mid);
	maketree(o<<1|1,mid+1,r);
	tree[o]=(tree[o<<1]+tree[o<<1|1])%p;
}
void insert(int o,int l,int r,int x,int y,long long v){
	if(x<=l&&r<=y){
		tree[o]=(tree[o]+v*(r-l+1))%p; lazy[o]=(lazy[o]+v)%p; return;
	}
	int mid=l+r>>1;
	if(lazy[o]) pushdown(o,l,r,mid);
	if(x<=mid) insert(o<<1,l,mid,x,y,v);
	if(y>mid) insert(o<<1|1,mid+1,r,x,y,v);
	tree[o]=(tree[o<<1]+tree[o<<1|1])%p;
}
long long sum(int o,int l,int r,int x,int y){
	if(x<=l&&r<=y) return tree[o]%p;
	int mid=l+r>>1,tot=0;
	if(lazy[o]) pushdown(o,l,r,mid);
	if(x<=mid) tot+=sum(o<<1,l,mid,x,y);
	if(y>mid) tot+=sum(o<<1|1,mid+1,r,x,y);
	return tot%p;
}
void add(int x,int y,long long v){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		insert(1,1,n,dfn[top[x]],dfn[x],v);
		x=fa[top[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	insert(1,1,n,dfn[y],dfn[x],v);
}
long long dis(int x,int y){
	long long ans=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		ans=(ans+sum(1,1,t,dfn[top[x]],dfn[x]))%p;
		x=fa[top[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	ans=(ans+sum(1,1,t,dfn[y],dfn[x]))%p;
	return ans%p;
}
int main(){
	freopen("data.in","r",stdin);
	scanf("%d %d %d %lld",&n,&m,&r,&p);
	for(int i=1;i<=n;i++)
		scanf("%lld",&val[i]);
	for(int i=1;i<=n-1;i++){
		scanf("%d %d",&a,&b);
		addway(a,b); addway(b,a);
	}
	dfs1(r,0,1); dfs2(r,r);
	maketree(1,1,t);
	for(int i=1;i<=m;i++){
		scanf("%d",&flag);
		if(flag==1){
			scanf("%lld %lld %lld",&a,&b,&c); c%=p;
			add(a,b,c);
		}
		else if(flag==2){
			scanf("%lld %lld",&a,&b);
			printf("%lld\n",dis(a,b)%p);
		}
		else if(flag==3){
			scanf("%lld %lld",&a,&b); b%=p;
			insert(1,1,t,dfn[a],dfn[a]+size[a]-1,b);
		}
		else {
			scanf("%lld",&a);
			printf("%lld\n",sum(1,1,t,dfn[a],dfn[a]+size[a]-1)%p);
		}
	}
	return 0;
}

回复

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

正在加载回复...