推荐博客:https://www.cnblogs.com/ivanovcraft/p/9019090.html
老实说,这篇博客写的很全,看完应该就会了;
核心代码喽~~
int df[maxn],idnew[maxn],son[maxn],fa[maxn],top[maxn],siz[maxn],depth[maxn],head[maxn],cnt1,cnt; struct edge{ int w,nx,to; }edge[maxn]; void add(int u,int v){ edge[++cnt].to=v; edge[cnt].nx=head[u]; head[u]=cnt; } void dfs1(int u,int fa)//找到重儿子,以及没棵子树的结点大小 { siz[u]=1;fa[u]=fa; for(int i=head[u];i;i=edge[i].nx){ int v=edge[i].to; if(u!=fa){ depth[v]=depth[u]+1; dfs(v,u); siz[u]+=siz[v]; if(siz[v]>siz[son[u]) son[u]=v; } } } void dfs2(int u,int t){ top[u]=t;//重链顶端 df[u]=++cnt1;//dfs序 idnew[cnt1]=u;//该dfs序代表的结点 if(!son[u]) return; dfs2(son[u],t); for(int i=head[u];i;i=edge[i].nx){ int v=edge[i].to; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); } }
表示:看完之后可能不是很会用,做一下模板题就ok~~
P3384 【模板】轻重链剖分
ran数组代表着线段树中的位置,用的是树剖+线段树维护
#include<iostream> #include<algorithm> #include<cstring> #include<set> #include<cstdio> #include<cmath> #include<map> using namespace std; #define maxn 500100 #define rson ((pos)*2+1) #define lson ((pos)*2) #define ll long long inline ll read(){ int out=0,flag=1;char c=getchar(); while(c<48||c>57) {if(c=='-') flag=-1;c=getchar();} while(c>=48&&c<=57) {out=out*10+c-48;c=getchar();} return out*flag; } ll son[maxn],siz[maxn],tot,val[maxn],depth[maxn],id[maxn],top[maxn],f[maxn],n,cnt,head[maxn]; ll tsum[maxn],lazy[maxn],m,r,p,ran[maxn]; struct edge{ ll to,nx,w; }edge[maxn]; void add(ll u,ll v) { edge[++cnt].nx=head[u]; edge[cnt].to=v; head[u]=cnt; } void dfs(ll u,ll fa) { siz[u]=1;depth[u]=depth[fa]+1;f[u]=fa; for(ll i=head[u];i;i=edge[i].nx) { ll v=edge[i].to; if(v!=fa) { dfs(v,u); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } return; } void dfs1(ll u,ll fa) { top[u]=fa; id[u]=++tot; ran[id[u]]=u; if(son[u]==-1) return; dfs1(son[u],fa); for(ll i=head[u];i;i=edge[i].nx) { ll v=edge[i].to; if(v!=son[u]&&v!=f[u]) dfs1(v,v); } } void build(ll pos,ll l,ll r) { if(l==r) {tsum[pos]=val[ran[l]]%p;return;} ll mid=(l+r)>>1; build(lson,l,mid); build(rson,mid+1,r); tsum[pos]=(tsum[lson]+tsum[rson])%p; } void pushdown(ll pos,ll l,ll r) { ll mid=(l+r)>>1; tsum[lson]=(tsum[lson]+(mid-l+1)*lazy[pos]%p)%p; tsum[rson]=(tsum[rson]+(r-mid)*lazy[pos]%p)%p; lazy[lson]=(lazy[lson]+lazy[pos]%p)%p; lazy[rson]=(lazy[rson]+lazy[pos]%p)%p; lazy[pos]=0; } void modify(ll pos,ll l,ll r,ll x,ll y,ll k) { if(x<=l&&y>=r){tsum[pos]=(tsum[pos]+(r-l+1)*k%p)%p,lazy[pos]=(lazy[pos]+k%p)%p;return;} ll mid=(l+r)>>1; pushdown(pos,l,r); if(x<=mid) modify(lson,l,mid,x,y,k); if(y>mid) modify(rson,mid+1,r,x,y,k); tsum[pos]=(tsum[lson]+tsum[rson])%p; } ll query(ll pos,ll l,ll r,ll x,ll y) { if(x<=l&&r<=y) return tsum[pos]%p; ll mid=(l+r)>>1; ll ret=0; pushdown(pos,l,r); if(x<=mid) ret+=query(lson,l,mid,x,y)%p; if(y>mid) ret+=query(rson,mid+1,r,x,y)%p; return ret%p; } void situation1(ll x,ll y,ll z) { while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); modify(1,1,n,id[top[x]],id[x],z); x=f[top[x]]; } if(id[x]>id[y]) swap(x,y); modify(1,1,n,id[x],id[y],z); } void situation2(ll x,ll y) { ll sum=0; while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); sum+=query(1,1,n,id[top[x]],id[x])%p; x=f[top[x]]; } if(id[x]>id[y]) swap(x,y); sum+=query(1,1,n,id[x],id[y])%p; cout<<sum%p<<endl; } void situation3(ll x,ll z) { modify(1,1,n,id[x],id[x]+siz[x]-1,z); } void situation4(ll x) { cout<<query(1,1,n,id[x],id[x]+siz[x]-1)%p<<endl; } int main() { fill(son,son+maxn,-1); n=read(),m=read(),r=read(),p=read(); for(int i=1;i<=n;i++) val[i]=read(); for(int i=1;i<n;i++) { ll x,y; x=read(),y=read(); add(x,y),add(y,x); } dfs(r,0); dfs1(r,0); build(1,1,n); while(m--) { ll q,x,y,z; q=read(); switch(q) { case 1:{ x=read();y=read(),z=read(); situation1(x,y,z); break; } case 2:{ x=read(),y=read(); situation2(x,y); break;} case 3:{ x=read(),z=read(); situation3(x,z); break;} case 4:{ x=read(); situation4(x); break;} } } }