树剖学习
主要分为两部分
剖分-dfs
树链的应用-线段树 LCA等
#include<iostream>
#include<cstdio>
#include<algorithm>
#define M 1001010
using namespace std;
//xx
int n,m,a[1001010],r,p;
struct note {
int l,r,tag,sum;
}c[1001010];
//tree
int ver[M],nex[M],head[M],cnt;
int siz[M],fa[M],dep[M],son[M];
//ll
int id[M],tot,cur[M],top[M];
///////////////add
inline void add(int x,int y) {
ver[++cnt]=y;
nex[cnt]=head[x];
head[x]=cnt;
}
///////////////main
void dfs1(int u) {
siz[u]=1;
for (int x=head[u];x;x=nex[x] ) {
int v=ver[x];
if(v!=fa[u]) {
dep[v]=dep[u]+1;
fa[v]=u;
dfs1(v);
siz[u]+=siz[v];
if (siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int t) {
id[u]=++tot;
cur[tot]=a[u];
top[u]=t;
if (son[u]) dfs2(son[u],t);
for (int x=head[u];x;x=nex[x]) {
int v=ver[x];
if (v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
///////////////////xianduanshu
inline int lson(int x) {return x<<1;}
inline int rson(int x) {return x<<1|1;}
inline int diss(int x) {return c[x].r-c[x].l+1;}
inline int mid(int l,int r) {return(l+r)>>1;}
inline void update(int x) {c[x].sum=c[lson(x)].sum+c[rson(x)].sum;}
void pushdown(int x) {
if (c[x].tag) {
c[lson(x)].sum+=c[x].tag*diss(lson(x));
c[rson(x)].sum+=c[x].tag*diss(rson(x));
c[lson(x)].tag+=c[x].tag;
c[rson(x)].tag+=c[x].tag;
c[x].tag=0;
}
}
void build(int x,int l,int r) {
c[x].l=l;c[x].r=r;
if (l==r) {
c[x].sum=cur[l];
return;
}
build(lson(x),l,mid(l,r));
build(rson(x),mid(l,r)+1,r);
update(x);
}
inline int query(int x,int l,int r) {
int ans=0;
if (c[x].l>=l&&c[x].r<=r)
return c[x].sum;
pushdown(x);
int mi=mid(c[x].l,c[x].r);
if (l<=mi) ans+=query(lson(x),l,r);
if (r>mi) ans+=query(rson(x),l,r);
return ans;
}
inline void change(int x,int l,int r,int d) {
if (c[x].l>=l&&c[x].r<=r) {
c[x].sum+=diss(x)*d;
c[x].tag+=d;
return;
}
pushdown(x);
int mi=mid(c[x].l,c[x].r);
if (l<=mi) change(lson(x),l,r,d);
if (r>mi) change(rson(x),l,r,d);
update(x);
return;
}
int calsum(int x,int y) {
int anss=0;
while (top[x]!=top[y]) {
if (dep[top[x]]<dep[top[y]]) swap(x,y);
anss+=query(1,id[top[x]],id[x]);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
anss+=query(1,id[x],id[y]);
return anss;
}
inline void calchan(int x,int y,int d) {
while (top[x]!=top[y]) {
if (dep[top[x]]<dep[top[y]]) swap(x,y);
change(1,id[top[x]],id[x],d);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
change(1,id[x],id[y],d);
}
int sonsum(int x) {
int ans=0;
ans+=query(1,id[x],id[x]+siz[x]-1);
return ans;
}
inline void sonchan(int x,int d) {
change(1,id[x],id[x]+siz[x]-1,d);
return;
}
////////////////mainn
int main() {
scanf("%d%d%d%d",&n,&m,&r,&p);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
int x,y,z;
for (int i=1;i<n;i++) {
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(r);
dfs2(r,r);
build(1,1,n);
int sc;
while (m--) {
scanf("%d",&sc);
if (sc==1) {
scanf("%d%d%d",&x,&y,&z);
calchan(x,y,z);
}
if (sc==2) {
scanf("%d%d",&x,&y);
printf("%d
",calsum(x,y)%p);
}
if (sc==3) {
scanf("%d%d",&x,&z);
sonchan(x,z);
}
if (sc==4) {
scanf("%d",&x);
printf("%d
",sonsum(x)%p);
}
}
return 0;
}