「ZJOI2008」树的统计

树剖模板题啊!

这道题的话,最通(jian)俗(dan)易(cu)懂(bao)的解法应该就是树剖了。
加上线段树维护树上路径的最大权值(\(Max\))和路径和(\(sum\))。
至于\(LCT\)这种高级操作对于我这种新手还是比较困难的\(qwq\)
以下是参考代码:(有什么问题欢迎指教!)

#include<cstdio>
const int MAXN=30010;
inline int max(int a,int b){return a>b?a:b;}
inline int read(){
	int s=0;bool f=false;char c=getchar();
	while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
	while(c>='0'&&c<='9')s=(s<<3)+(s<<1)+(c^48),c=getchar();
	return (f)?(-s):(s);
}
int n,m,summ,maxx;
int seg[MAXN],rev[MAXN],top[MAXN];
int dep[MAXN],siz[MAXN],son[MAXN],father[MAXN];
int tot,ver[MAXN<<1],fir[MAXN<<1],nxt[MAXN<<1];
inline void Add_edge(int u,int v){
	nxt[++tot]=fir[u],fir[u]=tot,ver[tot]=v;
	nxt[++tot]=fir[v],fir[v]=tot,ver[tot]=u;
}
int val[MAXN],sum[MAXN<<2],Max[MAXN<<2];
inline int lc(int rt){return rt<<1;}
inline int rc(int rt){return rt<<1|1;}
inline void push_sum(int rt){
	sum[rt]=sum[lc(rt)]+sum[rc(rt)];
}
inline void push_max(int rt){
	Max[rt]=max(Max[lc(rt)],Max[rc(rt)]);
}
inline void build(int rt,int l,int r){
	if(l==r)
		sum[rt]=Max[rt]=val[rev[l]];
	else{
		int mid=(l+r)>>1;
		build(lc(rt),l,mid);
		build(rc(rt),mid+1,r);
		push_sum(rt),push_max(rt);
	}
}
inline void update(int rt,int l,int r,int id,int v){
	if(id<l||id>r) return;
	if(l==r&&l==id)
		sum[rt]=Max[rt]=v;
	else{
		int mid=(l+r)>>1;
		update(lc(rt),l,mid,id,v);
		update(rc(rt),mid+1,r,id,v);
		push_sum(rt),push_max(rt);
	}
}
inline void query(int rt,int l,int r,int x,int y){
	if(r<x||l>y) return;
	if(x<=l&&r<=y)
		summ+=sum[rt],maxx=max(maxx,Max[rt]);
	else{
		int mid=(l+r)>>1;
		query(lc(rt),l,mid,x,y);
		query(rc(rt),mid+1,r,x,y);
	}
}
inline void dfs1(int u,int f){
	dep[u]=dep[f]+1,siz[u]=1,father[u]=f;
	for(int v,i=fir[u];i;i=nxt[i])
		if((v=ver[i])!=f){
			dfs1(v,u),siz[u]+=siz[v];
			if(siz[son[u]]<siz[v])son[u]=v;
		}
}
inline void dfs2(int u,int topf){
	top[rev[seg[u]=++seg[0]]=u]=topf;
	if(!son[u])return;else dfs2(son[u],topf);
	for(int v,i=fir[u];i;i=nxt[i])
		if(!top[v=ver[i]])dfs2(v,v);
}
inline void ask(int x,int y){
	int fx=top[x],fy=top[y];
	while(fx!=fy){
		if(dep[fx]>=dep[fy]){
			query(1,1,n,seg[fx],seg[x]);
			x=father[fx],fx=top[x];
		}
		else{
			query(1,1,n,seg[fy],seg[y]);
			y=father[fy],fy=top[y];
		}
	}
	if(dep[x]<=dep[y])
		query(1,1,n,seg[x],seg[y]);
	else
		query(1,1,n,seg[y],seg[x]);
}
int main(){
	n=read();
	for(int i=1;i<n;++i)
		Add_edge(read(),read());
	for(int i=1;i<=n;++i)
		val[i]=read();
	dfs1(1,0),dfs2(1,1),build(1,1,n);
	m=read();
	char opt[10];
	while(m--){
		scanf("%s",opt);
		int x=read(),y=read();
		if(opt[0]=='C')
			update(1,1,n,seg[x],y);
		else{
			summ=0;
			maxx=-10000000;
			ask(x,y);
			if(opt[1]=='M')
				printf("%d\n",maxx);
			else
				printf("%d\n",summ);
		}
	}
	return 0;
}
posted @ 2019-06-10 21:46  Sangber  阅读(148)  评论(0编辑  收藏  举报