zoukankan      html  css  js  c++  java
  • 树剖模板(洛谷P3384 【模板】树链剖分)(树链剖分,树状数组,树的dfn序)

    洛谷题目传送门

    仍然是一个板子。

    不过蒟蒻去学了一下BIT维护区间修改区间求和,常数果真十分优秀

    设数列为(a_i),差分数组(d_ i=a_ i-a_ {i-1}),前缀和(s_i=sumlimits_ {j=1}^ia_ j)

    显然有(a_ i=sumlimits_ {j=1}^id_ j)

    于是大力展开得到

    [s_i=sumlimits_{j=1}^i(i-j+1)d_j ]

    [s_i=(i+1)sumlimits_{i=1}^jd_j-sumlimits_{j=1}^ijd_j ]

    用BIT维护(d_i)(id_i)的前缀和即可。

    #include<cstdio>
    #define RG register
    #define R RG int
    #define G          if(++ip==ie)fread (ip=ibuf,1,L,stdin)
    #define P(C) *op=C;if(++op==oe)fwrite(op=obuf,1,L,stdout)
    typedef long long LL;
    const int N=1e5+9,M=N<<1,L=1<<19;
    char ibuf[L],*ie=ibuf+L,*ip=ie-1,obuf[L],*oe=obuf+L,*op=obuf;
    int YL,n,p,a[N],he[N],ne[M],to[M],f[N],s[N],id[N],pr[N],dep[N],top[N],d[N],e[N];
    inline int in(){
        G;while(*ip<'-')G;
        R x=*ip&15;G;
        while(*ip>'-'){(x*=10)+=*ip&15;G;}
        return x;
    }
    void out(R x){
        if(x>9)out(x/10);
        P(x%10|'0');
    }
    inline void swap(R&x,R&y){
        R z=x;x=y;y=z;
    }
    void dfs1(R x,R y){
        s[x]=1;
        dep[x]=dep[f[x]=y]+1;
        for(R i=he[x];i;i=ne[i])
            if(to[i]!=y)dfs1(to[i],x);
        s[y]+=s[x];
        if(s[pr[y]]<s[x])pr[y]=x;
    }
    void dfs2(R x,R y){
        top[x]=y;
        d[id[x]=++p]=a[x];
        if(!pr[x])return;
        dfs2(pr[x],y);
        for(R i=he[x];i;i=ne[i])
            if(!id[to[i]])dfs2(to[i],to[i]);
    }
    inline void mdf(R*d,R i,R v){
        for(;i<=n;i+=i&-i)(d[i]+=v)%=YL;
    }
    inline void upd(R l,R r,R v){
        mdf(d,l,v);mdf(e,l,(LL)v*l%YL);v=YL-v;
        mdf(d,r,v);mdf(e,r,(LL)v*r%YL);
    }
    inline int qry(R*d,R i){
        R v=0;
        for(;i;i-=i&-i)(v+=d[i])%=YL;
        return v;
    }
    inline int ask(R l,R r){
        return (((LL)(r+1)*qry(d,r)-qry(e,r)-(LL)(l+1)*qry(d,l)+qry(e,l))%YL+YL)%YL;
    }
    int main(){
        n=in();R m=in(),rt=in(),i,x,y,z,ans;YL=in();
        for(i=1;i<=n;++i)a[i]=in();
        for(i=1;i<n;++i){
            x=in();y=in();
            ne[++p]=he[x];to[he[x]=p]=y;
            ne[++p]=he[y];to[he[y]=p]=x;
        }
        p=0;dfs1(rt,0);dfs2(rt,rt);
        for(i=n;i;--i){
            d[i]=((d[i]-d[i-1])%YL+YL)%YL;
            e[i]=(LL)i*d[i]%YL;
        }
        for(i=1;i<=n;++i){
            if((x=i+(i&-i))>n)continue;
            (d[x]+=d[i])%=YL;(e[x]+=e[i])%=YL;
        }
        while(m--)
            switch(in()){
                case 1:x=in();y=in();z=in()%YL;
                    for(;top[x]!=top[y];x=f[top[x]]){
                        if(dep[top[x]]<dep[top[y]])swap(x,y);
                        upd(id[top[x]],id[x]+1,z);
                    }
                    if(dep[x]<dep[y])swap(x,y);
                    upd(id[y],id[x]+1,z);
                    break;
                case 2:x=in();y=in();ans=0;
                    for(;top[x]!=top[y];x=f[top[x]]){
                        if(dep[top[x]]<dep[top[y]])swap(x,y);
                        ans+=ask(id[top[x]]-1,id[x]);
                    }
                    if(dep[x]<dep[y])swap(x,y);
                    out((ans+ask(id[y]-1,id[x]))%YL);P('
    ');
                    break;
                case 3:x=in();z=in()%YL;
                    upd(id[x],id[x]+s[x],z);
                    break;
                case 4:x=in();
                    out(ask(id[x]-1,id[x]+s[x]-1));P('
    ');
            }
        fwrite(obuf,1,op-obuf,stdout);
        return 0;
    }
    
  • 相关阅读:
    UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)
    UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)
    【Same Tree】cpp
    【Recover Binary Search Tree】cpp
    【Binary Tree Zigzag Level Order Traversal】cpp
    【Binary Tree Level Order Traversal II 】cpp
    【Binary Tree Level Order Traversal】cpp
    【Binary Tree Post order Traversal】cpp
    【Binary Tree Inorder Traversal】cpp
    【Binary Tree Preorder Traversal】cpp
  • 原文地址:https://www.cnblogs.com/flashhu/p/9463786.html
Copyright © 2011-2022 走看看