一棵樹上有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
LCT:
一些操作: 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之間。
對於每個“QMAX”或者“QSUM”的操作,每行輸出一個整數表示要求輸出的結果。
Sample Input4 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 4Sample 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;
}