2019 ICPC Asia Shanghai - A Simple Problem On A Tree

题目链接: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;
}
发布了604 篇原创文章 · 获赞 242 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/104379609
今日推荐