• 树链剖分


    树链剖分

    #include<iostream>
    #include<cstdio>
    using namespace std;
    #define ci const int&
    #define ri register int
    #define rc register char
    #define ls rt<<1
    #define rs rt<<1|1
    #define N 100100
    struct edge{
        int nxt,to;
    } E[N<<1];
    struct node{
        int w,l,r,siz,lz;
    } T[N<<2];
    int n,m,r,p,x,y,z,op;
    int w[N],Tw[N];
    int cnt,rt;
    int head[N],fa[N],son[N],top[N],dep[N],siz[N],id[N];
    inline int read(){
        ri res=0,bf=1;
        rc c=getchar();
        for(;c<'0' || c>'9';c=getchar())
            if(c=='-')
                bf=-1;
        for(;c>='0' && c<='9';c=getchar())
            res=(res<<3)+(res<<1)+(c^'0');
        return bf*res;
    }
    void write(ci x){
        if(x>9)
            write(x/10);
        putchar(x%10^'0');
    }
    inline void add(ci u,ci v){
        E[++cnt].nxt=head[u];
        E[cnt].to=v;
        head[u]=cnt;
    }
    inline void pushup(ci rt){
        (T[rt].w=T[ls].w+T[rs].w)%=p;
    }
    inline void pushdown(ci rt){
        (T[ls].lz+=T[rt].lz)%=p;
        (T[rs].lz+=T[rt].lz)%=p;
        (T[ls].w+=T[rt].lz*T[ls].siz)%=p;
        (T[rs].w+=T[rt].lz*T[rs].siz)%=p;
        T[rt].lz=0;
    }
    void build(ci rt,ci l,ci r){
        T[rt].l=l,T[rt].r=r;
        T[rt].siz=r-l+1;
        if(l==r){
            T[rt].w=Tw[l];
            return;
        }
        ri mid=(l+r)>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(rt);
    }
    void update(ci rt,ci l,ci r,ci k){
        if(T[rt].l>=l && T[rt].r<=r){
            (T[rt].w+=T[rt].siz*k)%=p;
            (T[rt].lz+=k)%=p;
            return;
        }
        if(T[rt].lz)
            pushdown(rt);
        ri mid=(T[rt].l+T[rt].r)>>1;
        if(l<=mid)
            update(ls,l,r,k);
        if(r>mid)
            update(rs,l,r,k);
        pushup(rt);
    }
    int query(ci rt,ci l,ci r){
        if(T[rt].l>=l && T[rt].r<=r)
            return T[rt].w;
        if(T[rt].lz)
            pushdown(rt);
        ri res=0;
        ri mid=(T[rt].l+T[rt].r)>>1;
        if(l<=mid)
            res+=query(ls,l,r);
        if(r>mid)
            res+=query(rs,l,r);
        return res%p;
    }
    void dfs1(ci u,ci f,ci d){
        siz[u]=1;
        dep[u]=d;
        fa[u]=f;
        for(ri i=head[u];i;i=E[i].nxt){
            ri v=E[i].to;
            if(v==fa[u])
                continue;
            dfs1(v,u,d+1);
            siz[u]+=siz[v];
            if(siz[v]>siz[son[u]])
                son[u]=v;
        }
    }
    void dfs2(ci u,ci t){
        top[u]=t;
        id[u]=++cnt;
        Tw[cnt]=w[u];
        if(!son[u])
            return;
        dfs2(son[u],t);
        for(ri i=head[u];i;i=E[i].nxt){
            ri v=E[i].to;
            if(v==son[u] || v==fa[u])
                continue;
            dfs2(v,v);
        }
    }
    inline void Tadd(int x,int y,int k){
        for(;top[x]!=top[y];){
            if(dep[top[x]]<dep[top[y]])
                swap(x,y);
            update(1,id[top[x]],id[x],k);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])
            swap(x,y);
        update(1,id[x],id[y],k);
    }
    inline int Tsum(int x,int y){
        ri res=0;
        for(;top[x]!=top[y];){
            if(dep[top[x]]<dep[top[y]])
                swap(x,y);
            res+=query(1,id[top[x]],id[x])%p;
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])
            swap(x,y);
        res+=query(1,id[x],id[y]);
        return res%p;
    }
    int main(){
        n=read(),m=read(),r=read(),p=read();
        for(ri i=1;i<=n;i++)
            w[i]=read();
        for(ri i=1;i<n;i++){
            x=read(),y=read();
            add(x,y);
            add(y,x);
        }
        cnt=0;
        dfs1(r,0,1);
        dfs2(r,r);
        build(1,1,n);
        for(ri i=1;i<=m;i++){
            op=read();
            if(op==1){
                x=read(),y=read(),z=read();
                Tadd(x,y,z);
            }
            else if(op==2){
                x=read(),y=read();
                write(Tsum(x,y));
                puts("");
            }
            else if(op==3){
                x=read(),z=read();
                update(1,id[x],id[x]+siz[x]-1,z);
            }
            else if(op==4){
                x=read();
                write(query(1,id[x],id[x]+siz[x]-1));
                puts("");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    网页返回码大全
    求数组中子数组的最大和
    什么是面向对象?面向对象与面向过程的区别?
    Java内部类
    Java拆箱装箱
    linux中su和sudo区别
    Linux 中账户管理
    解决warn appiumdoctor bin directory for $java_home is not set
    Moco之include
    Mock server 之 Moco的使用
  • 原文地址:https://www.cnblogs.com/pelom/p/10279794.html
Copyright © 2020-2023  润新知