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:\n",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\n",solve(u,v));
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2020-12-05 21:39  starve_to_death  阅读(70)  评论(0编辑  收藏  举报