树链剖分模板
最近好像掉进什么奇怪的数据结构坑里去了。。。。
先放个板子,讲解和例题到时候在补上
# include<cstring> # include<iostream> # include<cstdio> # include<cmath> # include<cstdio> # include<algorithm> using std::swap; const int mn = 200005; struct edge{int to,next;}; edge e[mn*2]; int head[mn],edge_max; int n,m,r,mod; int val[mn],w[mn]; int deep[mn],siz[mn],fa[mn]; int id[mn],bl[mn],tot; struct tree{int l,r,sum,lazy;}; tree tr[mn*4]; void add(int x,int y) { e[++edge_max].to=y; e[edge_max].next=head[x]; head[x]=edge_max; } void dfs1(int x) { siz[x]=1; for(int i=head[x];i;i=e[i].next) { int u=e[i].to; if(u!=fa[x]) { deep[u]=deep[x]+1; fa[u]=x; dfs1(u); siz[x]+=siz[u]; } } } void dfs2(int x,int chain) { int k=0; id[x]=++tot; w[tot]=val[x]; bl[x]=chain; for(int i=head[x];i;i=e[i].next) { int u=e[i].to; if(deep[u]>deep[x] && siz[u]>siz[k]) k=u; } if(!k) return ; dfs2(k,chain); for(int i=head[x];i;i=e[i].next) { int u=e[i].to; if(deep[u]>deep[x] && u!=k) dfs2(u,u); } } void build(int l,int r,int cur) { tr[cur].l=l,tr[cur].r=r; if(l==r) { tr[cur].sum=(w[l])%mod; return ; } int mid=l+r>>1; build(l,mid,cur<<1); build(mid+1,r,cur<<1|1); tr[cur].sum=(tr[cur<<1].sum+tr[cur<<1|1].sum)%mod; } void pushdown(int cur) { if(tr[cur].lazy!=0) { tr[cur<<1].sum=(tr[cur<<1].sum+(tr[cur<<1].r-tr[cur<<1].l+1)*tr[cur].lazy)%mod; tr[cur<<1|1].sum=(tr[cur<<1|1].sum+(tr[cur<<1|1].r-tr[cur<<1|1].l+1)*tr[cur].lazy)%mod; tr[cur<<1].lazy=(tr[cur<<1].lazy+tr[cur].lazy)%mod; tr[cur<<1|1].lazy=(tr[cur<<1|1].lazy+tr[cur].lazy)%mod; tr[cur].lazy=0; } return ; } void update(int cur,int L,int R,int x) { if(tr[cur].l>R || tr[cur].r<L) return ; if(tr[cur].l>=L && tr[cur].r<=R) { tr[cur].sum=((tr[cur].r-tr[cur].l+1)*x+tr[cur].sum)%mod; tr[cur].lazy=(tr[cur].lazy+x)%mod; return ; } pushdown(cur); update(cur<<1,L,R,x); update(cur<<1|1,L,R,x); tr[cur].sum=(tr[cur<<1].sum+tr[cur<<1|1].sum)%mod; } void treeadd(int x,int y,int z) { while(bl[x]!=bl[y]) { if(deep[bl[x]]<deep[bl[y]]) swap(x,y); update(1,id[bl[x]],id[x],z); x=fa[bl[x]]; } if(deep[x]>deep[y]) swap(x,y); update(1,id[x],id[y],z); } int query(int cur,int L,int R) { if(tr[cur].l>=L && tr[cur].r<=R) return tr[cur].sum; if(tr[cur].l>R || tr[cur].r<L) return 0; pushdown(cur); int ans=0; ans=query(cur<<1,L,R); ans+=query(cur<<1|1,L,R); tr[cur].sum=(tr[cur<<1].sum+tr[cur<<1|1].sum)%mod; ans=ans%mod; return ans; } void treesum(int x,int y) { int ret=0; while(bl[x]!=bl[y]) { if(deep[bl[x]]<deep[bl[y]]) swap(x,y); ret=(ret+query(1,id[bl[x]],id[x]))%mod; x=fa[bl[x]]; } if(deep[x]>deep[y]) swap(x,y); ret=(ret+query(1,id[x],id[y]))%mod; printf("%d\n",ret); } int main() { int x,y,opt,z; scanf("%d%d%d%d",&n,&m,&r,&mod); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y),add(y,x); } deep[r]=1; dfs1(r); dfs2(r,r); build(1,n,1); for(int i=1;i<=m;i++) { scanf("%d%d",&opt,&x); if(opt==1) { scanf("%d%d",&y,&z); treeadd(x,y,z%mod); } else if(opt==2) { scanf("%d",&y); treesum(x,y); } else if(opt==3) { scanf("%d",&y); update(1,id[x],id[x]+siz[x]-1,y%mod); } else { printf("%d\n",query(1,id[x],id[x]+siz[x]-1)); } } return 0; }