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));
}
}
}