• F A Simple Problem On A Tree(区间加,区间乘,区间覆盖维护w*w*w)


    题:https://ac.nowcoder.com/acm/contest/4370/F

    题意:维护x3 支持区间加,区间覆盖,区间乘

    分析:

      码量题,其中区间覆盖可换成区间乘0+区间加w,

      lazy乘(设为y)对lazy加(设为w)有这样的影响:(x+w)*y,所以处理lazy乘时要对lazy加 进行加上w*y的操作

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define lson root<<1,l,midd
    #define rson root<<1|1,midd+1,r
    #define lc root<<1
    #define rc root<<1|1
    typedef long long ll;
    const int M=1e5+5;
    const int mod=1e9+7;
    int sz[M],dep[M],son[M],fa[M],top[M],dfn[M],to[M];
    ll tr[M<<2][4],lz[M<<2][4],val[M];
    vector<int>g[M];
    int n,cnt;
    void dfs1(int u,int f){
        fa[u]=f;
        sz[u]=1;dep[u]=dep[f]+1;
        for(auto v:g[u]){
            if(v!=f){
                dfs1(v,u);
                sz[u]+=sz[v];
                if(!son[u]||sz[v]>sz[son[u]])
                    son[u]=v;
            }
        }
    }
    void dfs2(int  u,int tp){
        top[u]=tp;
        dfn[u]=++cnt;
        to[cnt]=u;
        if(son[u])
            dfs2(son[u],tp);
        for(auto v:g[u]){
            if(v!=fa[u]&&v!=son[u])
                dfs2(v,v);
        }
    }
    void up(int root){
        for(int i=1;i<=3;i++)
            tr[root][i]=(tr[lc][i]+tr[rc][i])%mod;
        return ;
    }
    void add(int root,ll w,int l,int r){
        ll len=r-l+1;
        ll w1=w,w2=w*w%mod,w3=w*w%mod*w%mod;
        ll las1=tr[root][1],las2=tr[root][2];
        tr[root][1]=(tr[root][1]+len*w1%mod)%mod;
        tr[root][2]=(tr[root][2]+2ll*w1%mod*las1%mod+len*w2%mod)%mod;
        tr[root][3]=(tr[root][3]+3ll*w1%mod*las2%mod+3ll*w2%mod*las1%mod+len*w3%mod)%mod;
        return ;
    }
    void mul(int root,ll w){
        tr[root][1]=tr[root][1]*w%mod;
        tr[root][2]=tr[root][2]*w%mod*w%mod;
        tr[root][3]=tr[root][3]*w%mod*w%mod*w%mod;
    }
    void pushdown(int root,int l,int r){
        if(lz[root][1]!=1){
            ll tmp=lz[root][1];
            mul(lc,tmp),mul(rc,tmp);
            lz[lc][0]=lz[lc][0]*tmp%mod;
            lz[rc][0]=lz[rc][0]*tmp%mod;
            lz[lc][1]=lz[lc][1]*tmp%mod;
            lz[rc][1]=lz[rc][1]*tmp%mod;
            lz[root][1]=1;
        }
        if(lz[root][0]){
            ll tmp=lz[root][0];
            int midd=(l+r)>>1;
            add(lc,tmp,l,midd);
            add(rc,tmp,midd+1,r);
            lz[lc][0]=(lz[lc][0]+tmp)%mod;
            lz[rc][0]=(lz[rc][0]+tmp)%mod;
            lz[root][0]=0;
        }
        return ;
    }
    void updadd(int L,int R,ll w,int root,int l,int r){
        if(L<=l&&r<=R){
            lz[root][0]=(lz[root][0]+w)%mod;
            add(root,w,l,r);
            return ;
        }
        pushdown(root,l,r);
        int midd=(l+r)>>1;
        if(L<=midd)
            updadd(L,R,w,lson);
        if(R>midd)
            updadd(L,R,w,rson);
        up(root);
    }
    void soladd(int u,int v,ll w){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])
                swap(u,v);
            updadd(dfn[top[u]],dfn[u],w,1,1,n);
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])
            swap(u,v);
        updadd(dfn[v],dfn[u],w,1,1,n);
        return ;
    }
    void updmul(int L,int R,ll w,int root,int l,int r){
        if(L<=l&&r<=R){
            lz[root][0]=lz[root][0]*w%mod;
            lz[root][1]=lz[root][1]*w%mod;
            mul(root,w);
            return ;
        }
        pushdown(root,l,r);
        int midd=(l+r)>>1;
        if(L<=midd)
            updmul(L,R,w,lson);
        if(R>midd)
            updmul(L,R,w,rson);
        up(root);
        return ;
    }
    void solmul(int u,int v,ll w){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])
                swap(u,v);
            updmul(dfn[top[u]],dfn[u],w,1,1,n);
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])
            swap(u,v);
        updmul(dfn[v],dfn[u],w,1,1,n);
        return ;
    }
    ll query(int L,int R,int root,int l,int r){
        if(L<=l&&r<=R){
            return tr[root][3];
        }
        int midd=(l+r)>>1;
        pushdown(root,l,r);
        ll res=0;
        if(L<=midd)
            res=query(L,R,lson);
        if(R>midd)
            res=(res+query(L,R,rson))%mod;
        up(root);
        return res;
    }
    ll solve(int u,int v){
        ll ans=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])
                swap(u,v);
            ans=(ans+query(dfn[top[u]],dfn[u],1,1,n))%mod;
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])
            swap(u,v);
        ans=(ans+query(dfn[v],dfn[u],1,1,n))%mod;
        return ans;
    }
    void build(int root,int l,int r){
        for(int i=1;i<=3;i++)
            tr[root][i]=0;
        lz[root][0]=0;
        lz[root][1]=1;
        if(l==r){
            add(root,val[to[l]],l,r);
            return ;
        }
        int midd=(l+r)>>1;
        build(lson);
        build(rson);
        up(root);
        return ;
    }
    void init(){
        for(int i=1;i<=n;i++)
            g[i].clear(),son[i]=0,dep[i]=0;
        cnt=0;
    }
    int main(){
        int T;
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++){
            scanf("%d",&n);
            init();
            for(int u,v,i=1;i<n;i++){
                scanf("%d%d",&u,&v);
                g[u].pb(v);
                g[v].pb(u);
            }
    
    
            for(int i=1;i<=n;i++){
                scanf("%lld",&val[i]);
            }
            dfs1(1,0); dfs2(1,1);
            build(1,1,n);
            printf("Case #%d:
    ",cas);
            int m;
            scanf("%d",&m);
            while(m--){
                int op,u,v;
                ll w;
                scanf("%d%d%d",&op,&u,&v);
                if(op==1){
                    scanf("%lld",&w);
                    solmul(u,v,0);
                    soladd(u,v,w);
                }
                else if(op==2){
                    scanf("%lld",&w);
                    soladd(u,v,w);
                }
                else if(op==3){
                    scanf("%lld",&w);
                    solmul(u,v,w);
                }
                else{
                    printf("%lld
    ",solve(u,v));
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【并查集】连接格点C++
    【拓扑排序】威虎山上的分配C++
    CF39D Cubical PlanetC++
    【拓扑排序】排队C++
    [USACO09OCT]Invasion of the Milkweed】乳草的侵占C++
    免杀常用手段
    DELPHI 线程类
    动态注册OCX
    DELPHI 常用文件路径
    套接字(TCP)
  • 原文地址:https://www.cnblogs.com/starve/p/14091255.html
Copyright © 2020-2023  润新知