#树链剖分+线段树# [模板] [luoguP2590] [ZJOI2008]树的统计

Title

https://www.luogu.com.cn/problem/P2590


Solution

板子题


Code

#include<cstdio>
#define rr register 
#define ll long long 
using namespace std; 
const ll N=310000; 
const ll M=124000; 
ll n,m,Summ,Maxx; 
ll seg[N],rev[M],size[N],son[N],top[N],dep[N]; 
ll sum[M],num[N],father[N],Max[N],tot; 
ll first[M],next[M],go[M]; 
inline void myswap(ll &x,ll &y){x^=y^=x^=y; return;}
inline ll mymax(ll x,ll y){return x>y?x:y;}
inline void add(rr ll x,rr ll y){next[++tot]=first[x],first[x]=tot,go[tot]=y;}
inline void insert(rr ll x,rr ll y){add(x,y); add(y,x);}
inline ll get(){
	rr char c; 
	rr ll sign=1; 
	while ((c=getchar())<'0'||c>'9')
		if (c=='-') sign=-1; 
	rr ll res=c-'0'; 
	while((c=getchar())>='0'&&c<='9')
		res=res*10+c-'0'; 
	return res*sign; 
}
inline void build(rr ll k,rr ll l,rr ll r){
	rr ll mid=l+r>>1; 
	if (l==r){
		Max[k]=sum[k]=num[rev[l]]; 
		return; 
	}
	build(k<<1,l,mid),build((k<<1)+1,mid+1,r); 
	sum[k]=sum[k<<1]+sum[(k<<1)+1]; 
	Max[k]=mymax(Max[k<<1],Max[(k<<1)+1]); 
	return; 
}
inline void query(rr ll k,rr ll l,rr ll r,rr ll L,rr ll R){
	if (L>r||R<l) return; 
	if (L<=l&&r<=R){
		Summ+=sum[k],Maxx=mymax(Maxx,Max[k]); 
		return;
	}
	rr ll mid=l+r>>1,res=0; 
	if (mid>=L) query(k<<1,l,mid,L,R); 
	if (mid+1<=R) query((k<<1)+1,mid+1,r,L,R); 	
	return; 
}
inline void change(rr ll k,rr ll l,rr ll r,rr ll Val,rr ll pos){
	if (pos>r||pos<l) return; 
	if (l==r&&r==pos){
		sum[k]=Val,Max[k]=Val; 
		return; 
	}
	rr ll mid=l+r>>1; 
	if (mid>=pos) change(k<<1,l,mid,Val,pos); 
	if (mid+1<=pos) change((k<<1)+1,mid+1,r,Val,pos); 
	sum[k]=sum[k<<1]+sum[(k<<1)+1]; 
	Max[k]=mymax(Max[k<<1],Max[(k<<1)+1]); 
	return; 
}
inline void dfs1(rr ll u,rr ll f){
	rr ll e,v; 
	size[u]=1; 
	father[u]=f; 
	dep[u]=dep[f]+1; 
	for(e=first[u];v=go[e],e;e=next[e])
		if (v!=f){
			dfs1(v,u); 
			size[u]+=size[v]; 
			if (size[v]>size[son[u]]) son[u]=v; 
		}   
	return;                                
}                  
inline void dfs2(rr ll u,rr ll f){
	rr ll e,v; 
	if (son[u]){
		seg[son[u]]=++seg[0]; 
		top[son[u]]=top[u]; 
		rev[seg[0]]=son[u]; 
		dfs2(son[u],u); 
	}
	for(e=first[u];v=go[e],e;e=next[e])
		if(!top[v]){
			seg[v]=++seg[0]; 
			rev[seg[0]]=v; 
			top[v]=v; 
			dfs2(v,u); 
		}
	return; 
}
inline void ask(rr ll x,rr ll y){
	rr ll fx=top[x],fy=top[y]; 
	while(fx!=fy){
		if (dep[fx]<dep[fy]) myswap(x,y),myswap(fx,fy); 
		query(1,1,seg[0],seg[fx],seg[x]); 
		x=father[fx]; fx=top[x]; 
	}
	if (dep[x]>dep[y]) myswap(x,y); 
	query(1,1,seg[0],seg[x],seg[y]); 
	return;
}
inline void write(rr ll x){if (x>9) write(x/10); putchar(x%10+48);}
int main(){
	char sr[10]; 
	rr ll i,j,k,u,v,s1,s2; 
	n=get(); 
	for(i=1;i<n;i++) s1=get(),s2=get(),insert(s1,s2); 
	for(i=1;i<=n;i++) num[i]=get(); 
	dfs1(1,0); 
	seg[0]=seg[1]=top[1]=rev[1]=1; 
	dfs2(1,0); 
	build(1,1,seg[0]); 
	m=get(); 
	for(i=1;i<=m;i++){
		scanf("%s",sr+1),u=get(),v=get(); 
		if (sr[1]=='C') change(1,1,seg[0],v,seg[u]); 
		else{
			Summ=0,Maxx=-10000000; 
			ask(u,v); 
			if (sr[2]=='M') {if (Maxx<0) putchar('-'),write(-Maxx); else write(Maxx); putchar('\n');}
			else {if (Summ<0) putchar('-'),write(-Summ); else write(Summ); putchar('\n');}
		}
	}
	return 0; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值