• 树链剖分练习


    推荐博客: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;}
            }
        }
    }
  • 相关阅读:
    微信推送
    PS学习笔记
    汇编学习笔记
    JAVA学习笔记
    数组作为参数被传递,以及随机数的使用。
    [转]Win7系统中Telnet服务的安装和启动
    电脑高手学习笔记
    Android13.9.15
    C语言9.12
    《将博客搬至CSDN》
  • 原文地址:https://www.cnblogs.com/Showend/p/12562708.html
Copyright © 2020-2023  润新知