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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章