题目链接:2019 ICPC Asia Shanghai - A Simple Problem On A Tree
一道码农题。可能出题人想锻炼我们的代码能力。QAQ
就是线段树维护三次方,然后转到树上,就用树剖维护即可。
特别要注意几个lazy的转换。优先级也要注意。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10,mod=1e9+7;
int n,q,w[N]; vector<int> g[N];
int pos[N],bl[N],f[N],sz[N],h[N],son[N],cnt;
int s1[N<<2],s2[N<<2],s3[N<<2],atag[N<<2],cov[N<<2],mtag[N<<2];
inline int mul(int x,int y){return x*y%mod;}
inline int mul(int x,int y,int z){return x*y%mod*z%mod;}
inline int mul(int x,int y,int z,int c){return x*y%mod*z%mod*c%mod;}
inline int add(int x,int y){return (x+y)%mod;}
inline int add(int x,int y,int z){return (x+y+z)%mod;}
inline int add(int x,int y,int z,int c){return (x+y+z+c)%mod;}
inline void push_up(int p){
s1[p]=add(s1[p<<1],s1[p<<1|1]);
s2[p]=add(s2[p<<1],s2[p<<1|1]);
s3[p]=add(s3[p<<1],s3[p<<1|1]);
}
inline void push_down(int p,int l,int r){
int mid=l+r>>1;
if(cov[p]!=-1){
s1[p<<1]=mul(mid-l+1,cov[p]),s1[p<<1|1]=mul(r-mid,cov[p]);
s2[p<<1]=mul(mid-l+1,mul(cov[p],cov[p]));
s2[p<<1|1]=mul(r-mid,mul(cov[p],cov[p]));
s3[p<<1]=mul(mid-l+1,mul(cov[p],cov[p],cov[p]));
s3[p<<1|1]=mul(r-mid,mul(cov[p],cov[p],cov[p]));
atag[p<<1]=atag[p<<1|1]=0;
mtag[p<<1]=mtag[p<<1|1]=1;
cov[p<<1]=cov[p<<1|1]=cov[p];
cov[p]=-1;
}
if(mtag[p]!=1){
int tag=mul(mtag[p],mtag[p],mtag[p]);
s3[p<<1]=mul(s3[p<<1],tag),s3[p<<1|1]=mul(s3[p<<1|1],tag);
tag=mul(mtag[p],mtag[p]);
s2[p<<1]=mul(s2[p<<1],tag),s2[p<<1|1]=mul(s2[p<<1|1],tag);
s1[p<<1]=mul(s1[p<<1],mtag[p]),s1[p<<1|1]=mul(s1[p<<1|1],mtag[p]);
atag[p<<1]=mul(atag[p<<1],mtag[p]);
atag[p<<1|1]=mul(atag[p<<1|1],mtag[p]);
mtag[p<<1]=mul(mtag[p<<1],mtag[p]);
mtag[p<<1|1]=mul(mtag[p<<1|1],mtag[p]);
mtag[p]=1;
}
if(atag[p]!=0){
int c=atag[p];
s3[p<<1]=add(s3[p<<1],mul(mid-l+1,c,c,c),mul(3LL,s2[p<<1],c),mul(3LL,s1[p<<1],c,c));
s3[p<<1|1]=add(s3[p<<1|1],mul(r-mid,c,c,c),mul(3LL,s2[p<<1|1],c),mul(3LL,s1[p<<1|1],c,c));
s2[p<<1]=add(s2[p<<1],mul(mid-l+1,c,c),mul(2LL,s1[p<<1],c));
s2[p<<1|1]=add(s2[p<<1|1],mul(r-mid,c,c),mul(2LL,s1[p<<1|1],c));
s1[p<<1]=add(s1[p<<1],mul(mid-l+1,c));
s1[p<<1|1]=add(s1[p<<1|1],mul(r-mid,c));
atag[p<<1]=add(atag[p<<1],c);
atag[p<<1|1]=add(atag[p<<1|1],c);
atag[p]=0;
}
}
void build(int p,int l,int r){
atag[p]=0,mtag[p]=1,cov[p]=-1;
if(l==r) return ; int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
}
void change(int p,int l,int r,int ql,int qr,int v,int k){
if(l==ql&&r==qr){
if(k==1){
s1[p]=mul(r-l+1,v),s2[p]=mul(r-l+1,v,v),s3[p]=mul(r-l+1,v,v,v);
cov[p]=v,mtag[p]=1,atag[p]=0; return ;
}else if(k==2){
s3[p]=add(s3[p],mul(r-l+1,v,v,v),mul(3LL,s2[p],v),mul(3LL,s1[p],v,v));
s2[p]=add(s2[p],mul(r-l+1,v,v),mul(2LL,s1[p],v));
s1[p]=add(s1[p],mul(r-l+1,v));
atag[p]=add(atag[p],v); return ;
}else{
s3[p]=mul(s3[p],v,v,v),s2[p]=mul(s2[p],v,v),s1[p]=mul(s1[p],v);
mtag[p]=mul(mtag[p],v),atag[p]=mul(atag[p],v); return ;
}
return ;
}
int mid=l+r>>1; push_down(p,l,r);
if(qr<=mid) change(p<<1,l,mid,ql,qr,v,k);
else if(ql>mid) change(p<<1|1,mid+1,r,ql,qr,v,k);
else change(p<<1,l,mid,ql,mid,v,k),change(p<<1|1,mid+1,r,mid+1,qr,v,k);
push_up(p);
}
int ask(int p,int l,int r,int ql,int qr){
if(l==ql&&r==qr) return s3[p];
int mid=l+r>>1; push_down(p,l,r);
if(qr<=mid) return ask(p<<1,l,mid,ql,qr);
else if(ql>mid) return ask(p<<1|1,mid+1,r,ql,qr);
else return add(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
inline void init(){
for(int i=1;i<=n;i++) g[i].clear(); cnt=0;
memset(son,0,sizeof son);
}
void dfs1(int x){
sz[x]=1;
for(auto to:g[x]){
if(to==f[x]) continue;
f[to]=x; h[to]=h[x]+1;
dfs1(to); sz[x]+=sz[to];
if(sz[to]>sz[son[x]]) son[x]=to;
}
}
void dfs2(int x,int belong){
pos[x]=++cnt; bl[x]=belong;
if(son[x]) dfs2(son[x],belong);
for(auto to:g[x]) if(h[to]>h[x]&&to!=son[x]) dfs2(to,to);
}
inline void upd(int x,int y,int v,int k){
while(bl[x]!=bl[y]){
if(h[bl[x]]<h[bl[y]]) swap(x,y);
change(1,1,n,pos[bl[x]],pos[x],v,k); x=f[bl[x]];
}
if(pos[x]>pos[y]) swap(x,y);
change(1,1,n,pos[x],pos[y],v,k);
}
inline int asksum(int x,int y){
int res=0;
while(bl[x]!=bl[y]){
if(h[bl[x]]<h[bl[y]]) swap(x,y);
res=add(res,ask(1,1,n,pos[bl[x]],pos[x])); x=f[bl[x]];
}
if(pos[x]>pos[y]) swap(x,y);
res=add(res,ask(1,1,n,pos[x],pos[y]));
return res;
}
inline void solve(int id){
cin>>n; init();
for(int i=1,x,y;i<n;i++)
scanf("%lld %lld",&x,&y),g[x].push_back(y),g[y].push_back(x);
dfs1(1); dfs2(1,1);
for(int i=1;i<=n;i++) scanf("%lld",&w[i]);
build(1,1,n);
for(int i=1;i<=n;i++) change(1,1,n,pos[i],pos[i],w[i],1);
cin>>q; printf("Case #%lld:\n",id);
for(int i=1,op,u,v,w;i<=q;i++){
scanf("%lld %lld %lld",&op,&u,&v);
if(op!=4) scanf("%lld",&w),upd(u,v,w,op);
else printf("%lld\n",asksum(u,v));
}
}
signed main(){
int T; cin>>T;
for(int i=1;i<=T;i++) solve(i);
return 0;
}