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; }