社区讨论

树链剖分模板题样例RE,玄关

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

讨论操作

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

当前回复
0 条
当前快照
1 份
快照标识符
@mjla3nnx
此快照首次捕获于
2025/12/25 18:07
2 个月前
此快照最后确认于
2025/12/27 16:35
2 个月前
查看原帖
CPP
#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#define int long long
#define N 200005
#define lc u<<1
#define rc u<<1|1
using namespace std;
class SLPF{
	struct node{
		int l,r,sum,add;
	}tr[N*4];
	int cnt;
	int fa[N],dep[N],siz[N],son[N],top[N],id[N],nw[N];
public:
	int root;
	int w[N];
	vector<int> e[N];
protected:
	inline void pushup(int u){
		tr[u].sum=tr[lc].sum+tr[rc].sum;
		return ;
	}
	inline void pushdown(int u){
		if(tr[u].add){
			tr[lc].sum+=tr[u].add*(tr[lc].r-tr[lc].l-1);
			tr[rc].sum+=tr[u].add*(tr[rc].r-tr[rc].l-1);
			tr[lc].add+=tr[u].add;
			tr[rc].add+=tr[u].add;
			tr[u].add=0;
		}
	}
public:
	void build(int u,int l,int r){
		tr[u]={l,r,nw[l],0};
		if(l==r){
			return ;
		}
		int mid=l+r>>1;
		build(lc,l,mid);
		build(rc,mid+1,r);
		pushup(u);
		return ;
	}
	void dfs1(int u,int f){
		fa[u]=f;
		dep[u]=dep[f]+1;
		siz[u]=1;
		for(int v:e[u]){
			if(v==f){
				continue;
			}
			dfs1(v,u);
			siz[u]+=siz[v];
			if(siz[son[u]]<siz[v]){
				son[u]=v;
			}
		}
		return ;
	}
	void dfs2(int u,int tp){
		top[u]=tp;
		id[u]=++cnt;
		nw[cnt]=w[u];
		if(son[u]){
			dfs2(son[u],tp);
		}
		for(int v:e[u]){
			if(v==fa[u]||v==son[u]){
				continue;
			}
			dfs2(v,v);
		}
		return ;
	}
	void change(int u,int x,int y,int k){
		if(x>tr[u].r||y<tr[u].l){
			return ;
		}
		if(x<=tr[u].l&&tr[u].r<=y){
			tr[u].sum+=k*(tr[u].r-tr[u].l+1);
			tr[u].add+=k;
			return ;
		}
		pushdown(u);
		change(lc,x,y,k);
		change(rc,x,y,k);
		pushup(u);
		return ;
	}
	int query(int u,int x,int y){
		if(x>tr[u].r||y<tr[u].l){
			return 0;
		}
		if(x<=tr[u].l&&tr[u].r<=y){
			return tr[u].sum;
		}
		pushdown(u);
		return query(lc,x,y)+query(rc,x,y);
	}
	inline void change_path(int u,int v,int k){
		while(top[u]!=top[v]){
			if(dep[top[u]]<dep[top[v]]){
				swap(u,v);
				change(1,id[top[u]],id[u],k);
				u=fa[top[u]];
			}
		}
		if(dep[u]<dep[v]){
			swap(u,v);
		}
		change(1,id[v],id[u],k);
		return ;
	}
	inline void change_tree(int u,int k){
		change(1,id[u],id[u]+siz[u]-1,k);
		return ;
	}
	int query_path(int u,int v){
		int res=0;
		while(top[u]!=top[v]){
			if(dep[top[u]]<dep[top[v]]){
				swap(u,v);
			}
			res+=query(1,id[top[u]],id[u]);
			u=fa[top[u]];
		}
		if(dep[u]<dep[v]){
			swap(u,v);
		}
		res+=query(1,id[v],id[u]);
		return res;
	}
	int query_tree(int u){
		return query(1,id[u],id[u]+siz[u]-1);
	}
}t;
int n,m,Mod;
int w[N];
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m>>t.root>>Mod;
	for(int i=1;i<=n;i++){
		cin>>w[i];
	}
	for(int i=1;i<=n;i++){
		int a,b;
		cin>>a>>b;
		t.e[a].push_back(b);
		t.e[b].push_back(a);
	}
	t.dfs1(t.root,0);
	t.dfs2(t.root,t.root);
	t.build(1,1,n);
	while(m--){
		int op,x,y,z;
		cin>>op>>x;
		if(x==1){
			cin>>y>>z;
			t.change_path(x,y,z);
		}else if(x==2){
			cin>>y;
			cout<<t.query_path(x,y)%Mod<<'\n';
		}else if(x==3){
			cin>>y;
			t.change_tree(x,y);
		}else{
			cout<<t.query_tree(x)%Mod<<'\n';
		}
	}
	return 0;
}

回复

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

正在加载回复...