1、树链剖分
浅谈树链剖分
树链剖分模板
#include<bits/stdc++.h>
#define ll long long
#define INF 2147483647
#define mem(i,j) memset(i,j,sizeof(i))
#define F(i,j,n) for(register int i=j;i<=n;i++)
#define md p
using namespace std;
struct hahaha{
int from,to,nxt;
}s[200010];
int n,m,r,p,head[200010],cnt=0,pls[1000010];
int v[100010],f[100010],son[100010];
int dep[100010],top[100010],sz[100010];
int id[1000010],vt[1000010],num=0;
inline int read(){
int datta=0;char chchc=getchar();bool okoko=0;
while(chchc<'0'||chchc>'9'){if(chchc=='-')okoko=1;chchc=getchar();}
while(chchc>='0'&&chchc<='9'){datta=datta*10+chchc-'0';chchc=getchar();}
if(okoko==1)return -datta;
return datta;
}
inline void ins(int from,int to){
s[++cnt].from=from;
s[cnt].to=to;
s[cnt].nxt=head[from];
head[from]=cnt;
}
inline int dfs1(int from){
int tmp=0,tmx=0,ti=0;
for(int i=head[from];i;i=s[i].nxt){
int to=s[i].to;
if(to!=f[from]){
dep[to]=dep[from]+1;
f[to]=from;
tmp=dfs1(to);
sz[from]+=tmp;
if(tmp>tmx)
tmx=tmp,ti=to;
}
}
sz[from]++;
son[from]=ti;
return sz[from];
}
inline void dfs2(int from,int tp){
id[from]=++num,vt[num]=v[from];
if(son[from])
top[son[from]]=tp,dfs2(son[from],tp);
for(int i=head[from];i;i=s[i].nxt){
int to=s[i].to;
if(to!=f[from]&&to!=son[from])
top[to]=to,dfs2(to,to);
}
}
struct Segment_Tree{
#define ls u<<1
#define rs u<<1|1
#define mid ((l+r)>>1)
int tree[1000010];
void updata(int u){
tree[u]=(tree[ls]+tree[rs])%md;
}
void pushdown(int u,int l,int r){
if(!pls[u])
return ;
pls[ls]+=pls[u];
pls[rs]+=pls[u];
tree[ls]+=(mid-l+1)*(pls[u]);
tree[rs]+=(r-mid)*(pls[u]);
pls[u]=0;
}
void build_tree(int u,int l,int r){
if(l==r){
tree[u]=vt[l];
return ;
}
build_tree(ls,l,mid);
build_tree(rs,mid+1,r);
updata(u);
}
void change(int u,int l,int r,int x,int y,int z){
if(x<=l&&r<=y){
pls[u]+=z;
tree[u]+=(r-l+1)*z;
return ;
}
pushdown(u,l,r);
if(x<=mid)
change(ls,l,mid,x,y,z);
if(y>=mid+1)
change(rs,mid+1,r,x,y,z);
updata(u);
}
int ask(int u,int l,int r,int x,int y){
int res=0;
if(x<=l&&r<=y)
return tree[u];
pushdown(u,l,r);;
if(x<=mid)
res+=ask(ls,l,mid,x,y);
if(y>=mid+1)
res+=ask(rs,mid+1,r,x,y);
return res;
}
}T;
inline void cRange(int x,int y,int z){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])
swap(x,y);
T.change(1,1,n,id[top[x]],id[x],z);
x=f[top[x]];
}
if(dep[x]<dep[y])
swap(x,y);
T.change(1,1,n,id[y],id[x],z);
}
inline int qRange(int x,int y){
int res=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])
swap(x,y);
res+=T.ask(1,1,n,id[top[x]],id[x]);
res%=md;
x=f[top[x]];
}
if(dep[x]<dep[y])
swap(x,y);
res+=T.ask(1,1,n,id[y],id[x]);
res%=md;
return res;
}
inline void cTree(int x,int z){
T.change(1,1,n,id[x],id[x]+sz[x]-1,z);
}
inline int qTree(int x){
return T.ask(1,1,n,id[x],id[x]+sz[x]-1)%md;
}
int main(){
n=read();m=read();r=read();p=read();
F(i,1,n)
v[i]=read();
F(i,1,n-1){
int from=read(),to=read();
ins(from,to);ins(to,from);
}
dep[r]=1;
dfs1(r);
top[r]=r;
dfs2(r,r);
T.build_tree(1,1,n);
F(p,1,m){
int kd=read(),x,y,z;
if(kd==1)
x=read(),y=read(),z=read(),cRange(x,y,z);
if(kd==2)
x=read(),y=read(),printf("%d\n",qRange(x,y));
if(kd==3)
x=read(),z=read(),cTree(x,z);
if(kd==4)
x=read(),printf("%d\n",qTree(x));
}
return 0;
}