BZOJ1036 [ZJOI2008]树的统计Count 树链剖分

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1036


题意概括

  一个树,每个节点有一个权值。3种操作。

  1:修改某一个节点的权值。

  2:询问某两个节点间的权值和

  3:询问某两个节点之间的最大权值。


题解

  树链剖分裸题


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=30005,Inf=33333;
struct Edge{
	int cnt,y[N*2],nxt[N*2],fst[N];
	void clear(){
		cnt=0;
		memset(fst,0,sizeof fst);
	}
	void add(int a,int b){
		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
	}
}g;
int n,m,v[N],fa[N],size[N],son[N],depth[N],top[N],p[N],ap[N],cnp;
struct Tree{
	int m,s;
}t[N*4];
void Get_Gen_Info(int rt,int pre,int d){
	depth[rt]=d,size[rt]=1,fa[rt]=pre,son[rt]=-1;
	for (int i=g.fst[rt];i;i=g.nxt[i])
		if (g.y[i]!=pre){
			int s=g.y[i];
			Get_Gen_Info(s,rt,d+1);
			size[rt]+=size[s];
			if (son[rt]==-1||size[s]>size[son[rt]])
				son[rt]=s;
		}
}
void Get_Pos(int rt,int tp){
	top[rt]=tp,p[rt]=++cnp,ap[cnp]=rt;
	if (son[rt]==-1)
		return;
	else
		Get_Pos(son[rt],tp);
	for (int i=g.fst[rt];i;i=g.nxt[i]){
		int s=g.y[i];
		if (s!=fa[rt]&&s!=son[rt])	
			Get_Pos(s,s);
	}
}
void pushup(int rt){
	int ls=rt<<1,rs=ls|1;
	t[rt].m=max(t[ls].m,t[rs].m);
	t[rt].s=t[ls].s+t[rs].s;
}
void build(int rt,int le,int ri){
	if (le==ri){
		t[rt].m=t[rt].s=v[ap[le]];
		return;
	}
	int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
	build(ls,le,mid);
	build(rs,mid+1,ri);
	pushup(rt);
}
void change(int rt,int le,int ri,int pos,int v){
	if (le==ri){
		t[rt].m=t[rt].s=v;
		return;
	}
	int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
	if (pos<=mid)
		change(ls,le,mid,pos,v);
	else
		change(rs,mid+1,ri,pos,v);
	pushup(rt);
}
int query(int rt,int le,int ri,int xle,int xri,int ty){
	if (le>xri||ri<xle)
		return ty?0:-Inf;
	if (xle<=le&&ri<=xri)
		return ty?t[rt].s:t[rt].m;
	int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
	if (ty)
		return query(ls,le,mid,xle,xri,ty)+query(rs,mid+1,ri,xle,xri,ty);
	else
		return max(query(ls,le,mid,xle,xri,ty),query(rs,mid+1,ri,xle,xri,ty));
}
int find(int a,int b,int t){
	int f1=top[a],f2=top[b],ans=t?0:-Inf;
	while (f1!=f2){
		if (depth[f1]<depth[f2])
			swap(f1,f2),swap(a,b);
		if (t)
			ans+=query(1,1,n,p[f1],p[a],t);
		else
			ans=max(ans,query(1,1,n,p[f1],p[a],t));
		a=fa[f1],f1=top[a];
	}
	if (depth[a]>depth[b])
		swap(a,b);
	if (t)
		ans+=query(1,1,n,p[a],p[b],t);
	else
		ans=max(ans,query(1,1,n,p[a],p[b],t));
	return ans;
}
int main(){
	scanf("%d",&n);
	g.clear();
	for (int i=1,a,b;i<n;i++){
		scanf("%d%d",&a,&b);
		g.add(a,b);
		g.add(b,a);
	}
	for (int i=1;i<=n;i++)
		scanf("%d",&v[i]);
	cnp=0;
	Get_Gen_Info(1,0,0);
	Get_Pos(1,1);
	build(1,1,n);
	scanf("%d",&m);
	for (int i=1;i<=m;i++){
		char str[10];
		int a,b,t;
		scanf("%s%d%d",str,&a,&b);
		if (str[0]=='C')
			change(1,1,n,p[a],b);
		else {
			t=str[1]=='M'?0:1;
			printf("%d\n",find(a,b,t));
		}
	}
	return 0;
}

  

posted @ 2017-12-03 20:37  zzd233  阅读(266)  评论(0编辑  收藏  举报