Mnzn树链剖分调了有一个小时求助QAQ
查看原帖
Mnzn树链剖分调了有一个小时求助QAQ
526677
封禁用户楼主2023/7/12 20:50
#include<bits/stdc++.h>
using namespace std;
#define N 2*114514
#define M 1919810
#define ll long long
#define ls now<<1
#define rs now<<1|1
#define INF 1145141919810
ll n,a,b,c,w[N],q,root,mod;
ll opt;
struct xx{
	ll next,to,val;
}e[2*N];
ll head[2*N],cnt;
void add(ll x,ll y){
	e[++cnt].next=head[x];
	e[cnt].to=y;
	head[x]=cnt;
}
struct tree{
	ll l,r;
	ll sum,add;
	ll len;
}t[4*N];
ll f[N],dept[N],size[N],son[N];
//父节点/深度/字数大小/重儿子 
void dfs1(ll u,ll dep){ //处理出每个点的信息 
	size[u]=1;
	dept[u]=dep;
	for(int i=head[u];i;i=e[i].next){
		ll v=e[i].to;
		if(v==f[u]) continue;
		f[v]=u;
		dfs1(v,dep+1);
		size[u]+=size[v];
		if(size[v]>size[son[u]]) son[u]=v;
	}
}
ll top[N],dfn[N],rk[N],t_cnt; //记录重链,dfs序,重链节点对应点编号 
void dfs2(ll u,ll t){ //t为重链顶端 
	top[u]=t;
	dfn[u]=++t_cnt;
	rk[t_cnt]=u;
	if(!son[u]) return;
	dfs2(son[u],t);
	for(int i=head[u];i;i=e[i].next){
		ll v=e[i].to;
		if(v!=son[u]&&v!=f[u]) dfs2(v,v); //位于轻链底端则top为他本身
	}
}
void pushup(ll now){
	t[now].sum=t[ls].sum+t[rs].sum;
	t[now].sum%=mod;
}
void pushdown(ll now){
	t[ls].add+=t[now].add;
	t[ls].sum+=t[now].add*t[now].len;
	t[rs].add+=t[now].add;
	t[rs].sum+=t[now].add*t[now].len;
	t[now].add=0;
}
void build(ll now,ll l,ll r){
	t[now].l=l,t[now].r=r;
	t[now].len=r-l+1,t[now].add=0;
	if(l==r){
		t[now].sum=w[rk[l]];
		return;
	}
	ll mid=l+r>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(now);
}
void update(ll now,ll x,ll y,ll k){
	if(t[now].l>=x&&t[now].r<=y){
		t[now].add+=k;
		t[now].sum+=t[now].len*k;
		t[now].sum%=mod;
		return;
	}
	pushdown(now);
	ll mid=t[now].l+t[now].r>>1;
	if(x<=mid) update(ls,x,y,k);
	if(y>mid) update(rs,x,y,k);
	pushup(now);
}
void update_side(ll u,ll v,ll k){
	k%=mod;
	while(top[u]!=top[v]){
		if(dept[top[u]]<=dept[top[v]]) swap(u,v);
		update(1,dfn[top[u]],dfn[u],k);
		u=f[top[u]];
	}
	if(dept[u]<dept[v]) swap(u,v);
	update(1,dfn[u],dfn[v],k);
}
void update_son(ll x,ll k){
	update(1,dfn[x],dfn[x]+size[x]-1,k);
}
ll qsum(ll now,ll x,ll y){
	if(t[now].l>=x&&t[now].r<=y) return t[now].sum;
	ll mid=t[now].l+t[now].r>>1,ans=0;
	pushdown(now);
	if(x<=mid) ans+=qsum(ls,x,y),ans%=mod;
	if(y>mid) ans+=qsum(rs,x,y),ans%=mod;
	pushup(now);
	return ans;
}
ll QSUM(ll u,ll v){
	ll ans=0;
	while(top[u]!=top[v]){ //LCA 
		if(dept[top[u]]<dept[top[v]]) swap(u,v);
		ans+=qsum(1,dfn[top[u]],dfn[u]);
		ans%=mod;
		u=f[top[u]];
	}
	if(dept[u]<dept[v]) swap(u,v);
	ans+=qsum(1,dfn[v],dfn[u]);
	return ans;
}
ll QSON(ll x){
	return qsum(1,dfn[x],dfn[x]+size[x]-1)%mod; //注意
}
int main(){
	//ios::sync_with_stdio(0);
	//cin.tie(0); cout.tie(0);
	cin>>n>>q>>root>>mod;
	for(int i=1;i<=n;++i) cin>>w[i];
	for(int i=1;i<n;++i){
		cin>>a>>b;
		add(a,b);
		add(b,a);
	}
	dfs1(root,0); dfs2(root,root);
	build(1,1,n);
	//for(int i=1;i<=4*n;++i) cout<<t[i].len<<" "; cout<<'\n';
	while(q--){
		cin>>opt;
		if(opt==1) cin>>a>>b>>c,update_side(a,b,c);
		if(opt==2) cin>>a>>b,cout<<QSUM(a,b)%mod<<'\n';
		if(opt==3) cin>>a>>b,update_son(a,b);
		if(opt==4) cin>>a,cout<<QSON(a)%mod<<'\n'; 
		//for(int i=1;i<=4*n;++i) cout<<t[i].sum<<'\n';
	}
	return 0;
}
/*
5 5 2 24
7 3 7 8 0 
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
*/

样例都过不了,对拍也只拍了个寂寞

2023/7/12 20:50
加载中...