BZOJ1036 树的统计Count(LCT动态树)

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

Input

  输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有
一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作
的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

Output

  对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16

LCT:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#define F(x) tree[x].fa
#define LC(x) tree[x].child[0]
#define RC(x) tree[x].child[1]
#define REV(x) tree[x].rev
#define Size 300010
using namespace std;
inline int read(){
	int sum=0,fg=1;char c=getchar();
	while(c<'0' || c>'9'){if(c=='-')fg=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*fg;
}
struct lct{
	int fa,child[2],rev;
	int v,sum,MAX;
}tree[Size];
struct link_cut_tree{
	inline bool isroot(int x){
		return LC(F(x))!=x && RC(F(x))!=x;
	}
	inline void pushup(int x){
		tree[x].sum=tree[x].MAX=tree[x].v;
		if(LC(x)){tree[x].sum+=tree[LC(x)].sum;tree[x].MAX=max(tree[x].MAX,tree[LC(x)].MAX);}
		if(RC(x)){tree[x].sum+=tree[RC(x)].sum;tree[x].MAX=max(tree[x].MAX,tree[RC(x)].MAX);}
	}
	inline void pushdown(int x){
		if(REV(x)){
			REV(x)^=1;REV(LC(x))^=1;REV(RC(x))^=1;
			swap(LC(x),RC(x));
		}
	}
	void Pushdown(int x){
		if(!isroot(x))Pushdown(F(x));
		pushdown(x);
	}
	inline void rotate(int x){
		int A=F(x),B=F(A);bool w=(RC(A)==x);
		if(!isroot(A)){
			if(LC(B)==A)LC(B)=x;
			else if(RC(B)==A)RC(B)=x;
		}
		F(tree[x].child[w^1])=A;F(A)=x;F(x)=B;
		tree[A].child[w]=tree[x].child[w^1];tree[x].child[w^1]=A;
		pushup(A);pushup(x);
	}
	inline void splay(int x){
		Pushdown(x);
		while(!isroot(x)){
			if(!isroot(F(x)))rotate(x);
			rotate(x);
		}
	}
	inline void access(int x){
		for(int i=0;x;i=x,x=F(x)){splay(x),RC(x)=i,pushup(x);}
	}
	inline int find_root(int x){
		access(x);splay(x);while(LC(x))x=LC(x);
		return x;
	}
	inline void reverse(int x){
		access(x);splay(x);REV(x)^=1;
	}
	inline void link(int x,int y){
		reverse(x);F(x)=y;
	}
	inline void update(int x,int val){
		tree[x].sum=tree[x].MAX=tree[x].v=val;
		splay(x);pushup(x);
	}
	inline int query_max(int x,int y){
		reverse(x);access(y);splay(y);
		return tree[y].MAX;
	}
	inline int query_sum(int x,int y){
		reverse(x);access(y);splay(y);
		return tree[y].sum;
	}
}LCT;
int main(){
	int n=read();
	for(int i=1;i<n;i++){
		int x=read(),y=read();
		LCT.link(x,y);
	}
	for(int i=1;i<=n;i++){
		int val=read();
		LCT.update(i,val);
	}
	int m=read();
	while(m--){
		static char tp[10];
		scanf("%s",tp);
		if(tp[0]=='C'){
			int x=read(),val=read();
			LCT.update(x,val);
		}
		else if(tp[1]=='M'){
			int x=read(),y=read();
			printf("%d\n",LCT.query_max(x,y));
		}
		else{
			int x=read(),y=read();
			printf("%d\n",LCT.query_sum(x,y));
		}
	}
	return 0;
}



发布了83 篇原创文章 · 获赞 27 · 访问量 6万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章