P3384 树链剖分模板

复习(预习)一下树链剖分

Reference:https://www.cnblogs.com/chinhhh/p/7965433.html


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int tr[maxn<<2],lazy[maxn<<2];
int size[maxn],dep[maxn],fa[maxn],top[maxn],w[maxn],wt[maxn],son[maxn],id[maxn];
int n,m,r,times=0;
long long mod;
ll add(ll a,ll b){
	return (a+b+mod)%mod;
}
ll mul(ll a,ll b){
	return a*b%mod;
}
ll res=0;
void push_down(int o,int len){
	if(lazy[o]){
		lazy[o<<1]=add(lazy[o<<1],lazy[o]);
		lazy[o<<1|1]=add(lazy[o<<1|1],lazy[o]);
		tr[o<<1]=add(tr[o<<1],mul(lazy[o],len-len/2));
		tr[o<<1|1]=add(tr[o<<1|1],mul(lazy[o],len/2));
		lazy[o]=0;
	}
}
void build(int o,int l,int r){
	if(l==r){
		tr[o]=wt[l];
		return ;
	}
	int mid=l+r>>1;
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);
	tr[o]=add(tr[o<<1],tr[o<<1|1]);
}
void query(int o,int l,int r,int x,int y){
	if(x<=l&&y>=r){
		res=add(res,tr[o]);
		return ;
	}
	else {
		int mid=l+r>>1;
		push_down(o,r-l+1);
		if(mid>=x)query(o<<1,l,mid,x,y);
		if(mid<y)query(o<<1|1,mid+1,r,x,y);
	}
}
void update(int o,int l,int r,int x,int y,int k){
	if(x<=l&&y>=r){
		lazy[o]=add(lazy[o],k);
		tr[o]=add(tr[o],mul(k,r-l+1));
	}
	else {
		push_down(o,r-l+1);
		int mid=l+r>>1;
		if(mid>=x)update(o<<1,l,mid,x,y,k);
		if(mid<y)update(o<<1|1,mid+1,r,x,y,k);
		tr[o]=add(tr[o<<1],tr[o<<1|1]);
	}
}


struct Node{
	int next,to;
}edge[2*maxn];
int head[maxn];
int cnt=0;
void add_edge(int x,int y){
	edge[cnt].next=head[x];
	edge[cnt].to=y;
	head[x]=cnt++;
}
void dfs1(int x){
	size[x]=1,dep[x]=dep[fa[x]]+1;
	for(int i=head[x];i!=-1;i=edge[i].next){
		int y=edge[i].to;
		if(y!=fa[x]){
			fa[y]=x;dfs1(y);size[x]+=size[y];
			if(size[son[x]]<size[y]){
				son[x]=y;
			}
		}
	}
}
void dfs2(int x,int tp){
	top[x]=tp;id[x]=++times;wt[times]=w[x];
	if(son[x]==0)return ;
	dfs2(son[x],tp);
	for(int i=head[x];i!=-1;i=edge[i].next){
		int y=edge[i].to;
		if(y!=fa[x]&&y!=son[x]){
			dfs2(y,y);
		}
	}
}
int qRange(int x,int y){
	int ans=0;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		res=0;
		query(1,1,n,id[top[x]],id[x]);
		ans=add(ans,res);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y])swap(x,y);
	res=0;
	query(1,1,n,id[x],id[y]);
	ans=add(ans,res);
	return ans;
}
void updRange(int x,int y,int k){
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		update(1,1,n,id[top[x]],id[x],k);
		x=fa[top[x]];
	}
	if(dep[x]>dep[y])swap(x,y);
	update(1,1,n,id[x],id[y],k);
}
int qSon(int x){
	res=0;
	query(1,1,n,id[x],id[x]+size[x]-1);
	return res;
}
void updSon(int x,int k){
	update(1,1,n,id[x],id[x]+size[x]-1,k);
}
int main(){
	scanf("%d%d%d%lld",&n,&m,&r,&mod);
	head[0]=-1;
	for(int i=1;i<=n;i++)scanf("%d",&w[i]),head[i]=-1;
	for(int i=1;i<n;i++){
		int x,y;scanf("%d%d",&x,&y);add_edge(x,y);add_edge(y,x);
	}
	dfs1(r);
	dfs2(r,r);
	build(1,1,n);
	while(m--){
		int x,y,z;
		int op;
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d%d",&x,&y,&z);
			updRange(x,y,z);
		}
		if(op==2){
			scanf("%d%d",&x,&y);
			printf("%d\n",qRange(x,y));
		}
		if(op==3){
			scanf("%d%d",&x,&y);
			updSon(x,y);
		}
		if(op==4){
			scanf("%d",&x);
			printf("%d\n",qSon(x));
		}
	}

}

posted @ 2020-05-26 03:28  tttttttttrx  阅读(147)  评论(0编辑  收藏  举报