树链剖分求调
查看原帖
树链剖分求调
309320
懵逼小蒟蒻楼主2022/7/13 21:49

过不了样例……实在看不出来哪里寄了

#include<bits/stdc++.h>
using namespace std;
int n,m,r;
struct nd{
	int l,r,mid;
	long long s,ad;
}t[2000005];
int hd[500005],cnt=0,op;
int son[500005],tp[500005],cct,fa[500005],sz[500005],de[500005],ctn[500005];
long long yw[500005],nw[500005],x,y,z,q;
struct E{
	int v,nt;
}e[500005];
void dfs1(int p,int f,int ndp){
	de[p]=ndp;
	int yy,mxs=-1;
	sz[p]=1;
	for(int i = hd[p];i;i = e[i].nt){
		yy = e[i].v;
		if(yy == f)continue;
		fa[yy]=p;
		dfs1(yy,p,ndp+1);
		sz[p]+=sz[yy];
		if(sz[yy]>mxs){
			mxs=sz[yy];son[p]=yy;
		}
	}
}
void dfs2(int p,int f,int topn){
	int yy;
	ctn[p]=++cct;
	nw[cct]=yw[p];
	tp[p]=topn;
	if(!son[p])return; 
	dfs2(son[p],p,topn);
	for(int i = hd[p];i;i = e[i].nt){
		yy = e[i].v;
		if(yy==son[p]||yy==f)continue;
		dfs2(yy,p,yy);
	}
}
void add(int u,int v){
	e[cnt].v = v;
	e[cnt].nt = hd[u];
	hd[u] = cnt++; 
}
void ud(int p){
	t[p].s = t[p*2].s + t[p*2+1].s;
	t[p].s%=q;
}
void tag(int p){
	if(t[p].ad){
		t[p*2].s+=t[p].ad;
		t[p*2].s%=q;
		t[p*2+1].s+=t[p].ad;
		t[p*2+1].s%=q;
		t[p*2].ad+=t[p].ad;
		t[p*2].ad%=q;
		t[p*2+1].ad+=t[p].ad;
		t[p*2+1].ad%=q;
		t[p].ad=0;
	}
}
void build(int p,int l,int r){
	t[p].l = l;t[p].r = r;
	t[p].mid = l+r>>1; 
	if(l==r){
		t[p].s = nw[l]%q;
		return;
	}
	build(p*2,l,t[p].mid);
	build(p*2+1,t[p].mid+1,r);
	ud(p);
}
long long qr(int p,int l,int r){
	if(t[p].l>=l&&t[p].r<=r){
		return t[p].s;
	}
	tag(p);
	long long val=0;
	if(t[p].mid>=l)val+=qr(p*2,l,r);
	if(t[p].mid<r)val+=qr(p*2+1,l,r);
	return val%q;
}
void aq(int p,int l,int r,long long k){
	if(t[p].l>=l&&t[p].r<=r){
		t[p].s+=k;
		t[p].ad+=k;
		t[p].s%=q;
		t[p].ad%=k;
		return;
	}
	tag(p);
	if(t[p].mid>=l)aq(p*2,l,r,k);
	if(t[p].mid<r)aq(p*2+1,l,r,k);
	ud(p);
}
void aqot(int nx,int ny,long long k){
	while(tp[nx]!=tp[ny]){
		if(de[tp[nx]]<de[tp[ny]])swap(nx,ny);
		aq(1,ctn[tp[nx]],ctn[nx],k);
		nx = fa[tp[nx]];
	}
	if(de[nx]<de[ny])swap(nx,ny);
	aq(1,ctn[ny],ctn[nx],k);
}
long long qrot(int nx,int ny){
	long long sum=0;
	while(tp[nx]!=tp[ny]){
		if(de[tp[nx]]<de[tp[ny]])swap(nx,ny);
		sum+=qr(1,ctn[tp[nx]],ctn[nx]);
		sum%=q;
		nx = fa[tp[nx]];
	}
	if(de[nx]<de[ny])swap(nx,ny);
	sum+=qr(1,ctn[ny],ctn[nx]);
	return sum%q;
}
void aqoot(int p,long long k){
	aq(1,ctn[p],ctn[p]+sz[p]-1,k);
}
long long qroot(int p){
	return qr(1,ctn[p],ctn[p]+sz[p]-1);
}
int main(){
	scanf("%d%d%d%lld",&n,&m,&r,&q);
	for(int i = 1;i<=n;i++){
		scanf("%lld",&yw[i]);
	} 
	for(int i = 1;i<n;i++){
		scanf("%lld%lld",&x,&y);
		add(x,y);add(y,x);
	}
	dfs1(r,0,1);
	dfs2(r,0,r);
	build(1,1,n);
	while(m--){
		scanf("%d",&op);
		if(op==1){
			scanf("%lld%lld%lld",&x,&y,&z);
			aqot(x,y,z);
		}else if(op==2){
			scanf("%lld%lld",&x,&y);
			printf("%lld\n",qrot(x,y));
		}else if(op==3){
			scanf("%lld%lld",&x,&y);
			aqoot(x,y);
		}else{
			scanf("%lld",&x);
			printf("%lld\n",qroot(x));
		}
	}
	return 0;
} 
2022/7/13 21:49
加载中...