树剖板子题30分求调

P3384 【模板】重链剖分/树链剖分

@[bluespace](/user/211086) 喜闻乐见的取模炸掉了 建议封装一个函数啥的以免取模写炸) ```cpp #include<bits/stdc++.h> # define reg register # define N (10000005) # define int long long using namespace std; struct node{ int l; int r; int sum; int lazy; }t[N]; int n,m,r,P; int num[N]; int head[N],nxt[N],to[N],tot; int rev[N],seg[N],top[N],fa[N],size[N],son[N],dep[N],sum; inline int read(){ char c=getchar();reg int sum=0,f=1; while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c<='9'&&c>='0'){sum=sum*10+c-'0';c=getchar();} return sum*f; } inline void update(const int &p){ if(t[p].lazy){ t[p<<1].lazy=(t[p<<1].lazy+t[p].lazy)%P; t[p<<1|1].lazy=(t[p<<1|1].lazy+t[p].lazy)%P; t[p<<1].lazy%=P;t[p<<1|1].lazy%=P; t[p<<1].sum+=(t[p<<1].r-t[p<<1].l+1)*t[p].lazy%P; t[p<<1|1].sum+=(t[p<<1|1].r-t[p<<1|1].l+1)*t[p].lazy%P; t[p<<1].sum%=P;t[p<<1|1].sum%=P; t[p].lazy=0; } } void build(const int &p,const int &l,const int &r){ t[p].l=l; t[p].r=r; t[p].sum=0; t[p].lazy=0; if(l==r){ t[p].sum=num[rev[l]]; return; } reg int mid=l+r>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); t[p].sum=(t[p<<1].sum+t[p<<1|1].sum)%P; } void change(const int &p,const int &l,const int &r,const int &k){ if(t[p].l>=l&&t[p].r<=r){ t[p].lazy=(t[p].lazy+k)%P; t[p].sum=(t[p].sum+(t[p].r-t[p].l+1)%P*k%P)%P; return; } update(p); reg int mid=t[p].l+t[p].r>>1; if(mid>=l)change(p<<1,l,r,k); if(mid<r)change(p<<1|1,l,r,k); t[p].sum=(t[p<<1].sum+t[p<<1|1].sum)%P; } int query(const int &p,const int &l,const int &r){ if(t[p].l>=l&&t[p].r<=r)return t[p].sum; update(p); reg int mid=t[p].l+t[p].r>>1,ans=0; if(mid>=l)ans+=query(p<<1,l,r),ans%=P; if(mid<r)ans+=query(p<<1|1,l,r),ans%=P; return ans; } inline void add(const int &x,const int &y){ to[++tot]=y;nxt[tot]=head[x];head[x]=tot; to[++tot]=x;nxt[tot]=head[y];head[y]=tot; } void dfs1(const int &u,const int &f){ reg int v; size[u]=1; fa[u]=f; dep[u]=dep[f]+1; for(reg int i=head[u];i;i=nxt[i]){ v=to[i]; if(v==f)continue; dfs1(v,u); size[u]+=size[v]; if(size[v]>size[son[u]]) son[u]=v; } } void dfs2(const int &u,const int &r){ reg int v; seg[u]=++sum; rev[sum]=u; top[u]=r; if(!son[u])return; dfs2(son[u],r); for(reg int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } inline void ask1(int x,int y,int z){ int fx=top[x],fy=top[y]; while(fx!=fy){ if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy); change(1,seg[fx],seg[x],z); x=fa[fx];fx=top[x]; } if(dep[x]>dep[y])change(1,seg[y],seg[x],z); else change(1,seg[x],seg[y],z); } inline int ask2(int x,int y){ int ans=0; int fx=top[x],fy=top[y]; while(fx!=fy){ if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy); ans=(ans+query(1,seg[fx],seg[x]))%P; x=fa[fx];fx=top[x]; } if(dep[x]>dep[y])ans=(ans+query(1,seg[y],seg[x]))%P; else ans=(ans+query(1,seg[x],seg[y]))%P; return ans; } inline void ask3(const int &x,const int &z){change(1,seg[x],seg[x]+size[x]-1,z);} inline int ask4(const int &x){return query(1,seg[x],seg[x]+size[x]-1);} signed main(){ reg int i,j,k,x,y,z; n=read();m=read();r=read();P=read(); for(i=1;i<=n;++i) num[i]=read(); for(i=1;i<n;++i){ x=read(); y=read(); add(x,y); } dfs1(r,0); dfs2(r,r); build(1,1,n); for(i=1;i<=m;++i){ k=read(); if(k==1){ x=read();y=read();z=read(); ask1(x,y,z); } if(k==2){ x=read();y=read(); printf("%d\n",ask2(x,y)); } if(k==3){ x=read();z=read(); ask3(x,z); } if(k==4){ x=read(); printf("%d\n",ask4(x)); } } return 0; } ```
by Refined_heart @ 2021-09-30 07:48:53


@[Refined_heart](/user/128591) 多谢,终于过了,大佬能讲一下怎么封装吗
by bsTiat @ 2021-09-30 12:33:09


@[bluespace](/user/211086) 我是习惯: ```cpp const int mod=... inline int Add(int x,int y){return (x+y)%mod;} inline int Mul(int x,int y){return 1ll*x*y%mod;} ``` 调用就直接用这俩就好
by Refined_heart @ 2021-09-30 18:05:46


@[Refined_heart](/user/128591) 好的,多谢
by bsTiat @ 2021-09-30 20:12:50


@[bluespace](/user/211086) 没事
by Refined_heart @ 2021-09-30 20:37:11


|