zoukankan      html  css  js  c++  java
  • 【数据结构】——洛谷P3384 树链剖分

    蓝书上的树剖用不习惯,今日发现一篇julao的树剖题解,格式工整,简单易记,富有条理,因此学习之。

    原题:GO

    julao的blog:GO


    具体的不讲了,直接上代码吧(已经过我的码风熏陶)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    int n,m,r,mod,tot,ans;
    int w[N],dep[N],siz[N],fa[N],son[N],top[N],id[N],w2[N];
    int at[N<<1],sum[N<<1];
    inline int read(){
        int f=1,x=0;
        char c=getchar();
        while(!isdigit(c)){
            if(c=='-') f=-1;
            c=getchar();
        } 
        while(isdigit(c)){
            x=x*10+c-'0';
            c=getchar();
        } 
        return x*f;
    }
    int head[N],cnt;
    struct edge{ int to,next; }e[N<<1];
    inline void addedge(int from,int to){ e[++cnt]=(edge){to,head[from]};head[from]=cnt; }
    inline void add(int x,int y){addedge(x,y),addedge(y,x);}
    void dfs1(int u,int f){
        dep[u]=dep[f]+1;
        siz[u]=1;
        fa[u]=f;
        int maxson=0;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==f) continue;
            dfs1(v,u);
            siz[u]+=siz[v];
            if(siz[v]>maxson) maxson=siz[v],son[u]=v;
        }
    }
    void dfs2(int u,int f){
        id[u]=++tot;
        w2[tot]=w[u];
        top[u]=f;
        if(!son[u]) return;
        dfs2(son[u],f);
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(v==fa[u]||v==son[u]) continue;
            dfs2(v,v);
        }
    }
    
    inline int ls(int o){return o<<1;}
    inline int rs(int o){return o<<1|1;}
    inline void pd(int o,int l,int r,int num){
        at[o]+=num;
        sum[o]+=(r-l+1)*num;
        sum[o]%=mod;
    }
    inline void pushdown(int o,int l,int r){
        int mid=(l+r)>>1;
        pd(ls(o),l,mid,at[o]);
        pd(rs(o),mid+1,r,at[o]);
        at[o]=0;
    }
    inline void pushup(int o){
        sum[o]=(sum[ls(o)]+sum[rs(o)])%mod;
    }
    void build(int o,int l,int r){
        if(l==r){
            sum[o]=w2[l];
            if(sum[o]>mod) sum[o]%=mod;
            return;
        }
        int mid=(l+r)>>1;
        build(ls(o),l,mid);
        build(rs(o),mid+1,r);
        pushup(o);
    }
    void change(int o,int l,int r,int x,int y,int k){
        if(l>y||r<x) return;
        if(x<=l&&r<=y){
            sum[o]+=(r-l+1)*k;
            at[o]+=k;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(o,l,r);
        if(x<=mid) change(ls(o),l,mid,x,y,k);
        if(y>mid) change(rs(o),mid+1,r,x,y,k);
        pushup(o);
    }
    void query(int o,int l,int r,int x,int y){
        if(l>y||r<x) return;
        if(x<=l&&r<=y){
            ans+=sum[o];
            ans%=mod;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(o,l,r);
        if(x<=mid) query(ls(o),l,mid,x,y);
        if(y>mid) query(rs(o),mid+1,r,x,y);
    }
    inline int ask(int u,int v){
        int cur=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            ans=0;
            query(1,1,n,id[top[u]],id[u]);
            cur+=ans;
            cur%=mod;
            u=fa[top[u]];
        }
        ans=0;
        if(dep[u]>dep[v]) swap(u,v);
        query(1,1,n,id[u],id[v]);
        cur+=ans;
        return cur%mod;
    }
    inline void ask2(int u,int v,int k){
        k%=mod;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            change(1,1,n,id[top[u]],id[u],k);
            u=fa[top[u]];
        }
        if(dep[u]>dep[v]) swap(u,v);
        change(1,1,n,id[u],id[v],k);
    }
    int main(){
        n=read();m=read();r=read();mod=read();
        for(register int i=1;i<=n;i++) w[i]=read();
        int k,x,y,z;
        for(register int i=1;i<n;i++) add(read(),read());
        dfs1(r,0);
        dfs2(r,r);
        build(1,1,n);
        for(register int i=1;i<=m;i++){
            k=read();
            if(k==1){
                x=read();y=read();z=read();
                ask2(x,y,z);
            }
            else if(k==2){
                x=read();y=read();
                printf("%d
    ",ask(x,y));
            }
            else if(k==3){
                x=read();z=read();
                change(1,1,n,id[x],id[x]+siz[x]-1,z);
            }
            else{
                x=read();ans=0;
                query(1,1,n,id[x],id[x]+siz[x]-1);
                printf("%d
    ",ans);
            }
        }
        return 0;
    } 
    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    Linux操作系统分析之进程的创建与可执行程序的加载
    Linux操作系统分析之计算机是怎样工作的
    求二项分布的数学期望与方差的工式及证明过程
    世界就是一个班
    软件版妻子
    时代变迁
    也许ASP真的不行了???
    新一字诗
    祝女同志节日快乐!
    写啥
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11545416.html
Copyright © 2011-2022 走看看