树链剖分练习

推荐博客: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
#include
#include
#include<set>
#include
#include
#include
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<endl;
}
void situation3(ll x,ll z)
{
    modify(1,1,n,id[x],id[x]+siz[x]-1,z);
}
void situation4(ll x)
{
    cout<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)
    {
        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;}
        }
    }
}

 

你可能感兴趣的:(树链剖分练习)