zoukankan      html  css  js  c++  java
  • [模板]树链剖分

    原题链接:https://www.luogu.org/problemnew/show/P3384

    树链剖分+线段树,备用。

    等待补充详细解释中。

    /*
    1 x y z  x到y最短路径上加上z
    2 x y 求x到y的最短路径上的节点值之和 
    3 x z 以x为根节点的子树内的所有节点值都加上z 
    4 x 以x为根节点的所有节点值之和 
    */
    #include<cstdio>
    void read(int &y)
    {
        y=0;char x=getchar();int f=1;
        while(x<'0'||x>'9')
        {
            if(x=='-') f=-1;
            x=getchar();
        }
        while(x>='0'&&x<='9')
        {
            y=y*10+x-'0';
            x=getchar();
        }
        y*=f;
    }
    struct edge
    {
        int u,v;
    }e[200005];
    int n,m,s,p,cnt,maxson,tot;
    int head[100005];
    int dep[100005],fa[100005],siz[100005];
    int id[100005],wt[100005],w[100005];
    int son[100005],top[100005];
    int a[400005],lz[400005];
    long long res;
    void swap(int &a,int &b)
    {
        int t=a;
        a=b;
        b=t;
    }
    void add(int u,int v)
    {
        e[++cnt].u=head[u];
        e[cnt].v=v;
        head[u]=cnt;
    }
    void dfs1(int x,int f,int deep)
    {
        dep[x]=deep;
        fa[x]=f;
        siz[x]=1;
        int maxson=-1;
        for(int i=head[x];i;i=e[i].u)
        {
            int t=e[i].v;
            if(t==f) continue;
            dfs1(t,x,deep+1);
            siz[x]+=siz[t];
            if(siz[t]>maxson)
            {
                son[x]=t;
                maxson=siz[t];
            }
        }
    }
    void dfs2(int x,int topf)
    {
        id[x]=++tot;
        wt[tot]=w[x];
        top[x]=topf;
        if(!son[x]) return;
        dfs2(son[x],topf);
        for(int i=head[x];i;i=e[i].u)
        {
            int t=e[i].v;
            if(t==fa[x]||t==son[x]) continue;
            dfs2(t,t);
        }
    }
    void build(int o,int l,int r)
    {
        if(l==r)
        {
            a[o]=wt[l]%p;
            return;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
        a[o]=(a[o<<1]+a[o<<1|1])%p;
    }
    void putdown(int o,int l,int r)
    {
        lz[o<<1]+=lz[o];
        lz[o<<1|1]+=lz[o];
        int mid=(l+r)>>1;
        a[o<<1]+=lz[o]*(mid-l+1);a[o<<1]%=p;
        a[o<<1|1]+=lz[o]*(r-mid);a[o<<1|1]%=p;
        lz[o]=0;
    }
    void query(int ll,int rr,int o,int l,int r)
    {
        if(ll<=l&&rr>=r)
        {
            res=(res+a[o])%p;
            return;
        }
        if(lz[o]) putdown(o,l,r);
        int mid=(l+r)>>1;
        if(ll<=mid) query(ll,rr,o<<1,l,mid);
        if(rr>mid) query(ll,rr,o<<1|1,mid+1,r);
    }
    void update(int k,int ll,int rr,int o,int l,int r)
    {
        if(ll<=l&&rr>=r)
        {
            lz[o]+=k;
            a[o]=(a[o]+k*(r-l+1))%p;
        }
        else
        {
            if(lz[o]) putdown(o,l,r);
            int mid=(l+r)>>1;
            if(ll<=mid) update(k,ll,rr,o<<1,l,mid);
            if(rr>mid) update(k,ll,rr,o<<1|1,mid+1,r);
            a[o]=(a[o<<1]+a[o<<1|1])%p;
        }
    }
    int qy(int x,int y)
    {
        int ans=0;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            res=0; 
            query(id[top[x]],id[x],1,1,n);
            ans=(ans+res)%p;
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        res=0;
        query(id[x],id[y],1,1,n);
        ans+=res;
        return ans%p;
    }
    void upy(int x,int y,int k)
    {
        k%=p;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            update(k,id[top[x]],id[x],1,1,n);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        update(k,id[x],id[y],1,1,n);
    }
    int qson(int x)
    {
        res=0;
        query(id[x],id[x]+siz[x]-1,1,1,n);
        return res;
    }
    void upd(int x,int k)
    {
        k%=p;
        update(k,id[x],id[x]+siz[x]-1,1,1,n);
    } 
    int main()
    {
        int op,x,y,z;
        read(n);read(m);read(s);read(p);
        for(int i=1;i<=n;i++) read(w[i]);
        for(int i=1;i<n;i++)
        {
            read(x);read(y);
            add(x,y);
            add(y,x);
        }
        dfs1(s,0,1);
        dfs2(s,s);
        build(1,1,n);
        while(m--)
        {
            read(op);
            if(op==1)
            {
                read(x);read(y);read(z);
                upy(x,y,z);
            }
            else if(op==2)
            {
                read(x);read(y);
                printf("%d
    ",qy(x,y));
            }
            else if(op==3)
            {
                read(x);read(z);
                upd(x,z);
            }
            else
            {
                read(x);
                printf("%d
    ",qson(x));
            }
        }
        return 0;
    }
  • 相关阅读:
    kali渗透综合靶机(八)--Billu_b0x靶机
    kali渗透综合靶机(七)--Super-Mario-Host靶机
    kali渗透综合靶机(九)--Typhoon靶机
    【Flask】 python学习第一章
    【HICP Gaussdb】数据库 数据库管理(连接方式 会话模式 存储表空间)-6
    【HICP Gaussdb】数据库 数据库管理(shutdown 日志 连接命令)-5
    【HCIA Gaussdb】学习汇总-数据库管理(数据库基本概念)-3
    【Flask】 python学习第一章
    【HCIA Gaussdb】学习汇总-数据库管理-2
    【HICP Gaussdb】数据库 数据库管理(调优 启动流程)-4
  • 原文地址:https://www.cnblogs.com/zeroform/p/8342011.html
Copyright © 2011-2022 走看看