Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。
我们将以下面的形式来要求你对这棵树完成一些操作:
I.CHANGE u t : 把结点u的权值改为t
II.QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III.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
树剖模板题。
//脱壳壳,结构体+inline+vector会re
#include<bits/stdc++.h>
#define N 50001
using namespace std;
inline int get(){register int re=0,f=1;register char c;while(c=getchar(),(c>='0'&&c<='9')^1)f=c^'-';while(re=(re<<1)+(re<<3)+(c^48),c=getchar(),(c>='0'&&c<='9'));return f?re:-re;}
#define FOR(i,L,R) for(register int i=(L);i<=(R);++i)
#define REP(i,R,L) for(register int i=(R);i>=(L);--i)
int n,m,cnt;
struct Graph{//构图finish
vector<int>G[N];
int p[N],fa[N];
int siz[N],son[N],dep[N];
int top[N];
#define to G[x][i]
inline void dfs2(int x,int sp){
top[x]=sp;
p[x]=++cnt;
if(son[x])dfs2(son[x],sp);
int sz=G[x].size()-1;
FOR(i,0,sz)if(to^fa[x]&&to^son[x])dfs2(to,to);
}
inline void dfs1(int x,int Fa,int depth){
int sz=G[x].size()-1;
FOR(i,0,sz)if(to^Fa){
dfs1(to,fa[to]=x,dep[to]=depth+1);
siz[x]+=siz[to];
if(siz[son[x]]<siz[to])son[x]=to;
}
}
inline void init(){
scanf("%d",&n);
FOR(i,1,n-1){
int x,y;scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}FOR(i,1,n)siz[i]=1;
}
}g;
#define top(a) g.top[a]
#define dep(a) g.dep[a]
#define p(a) g.p[a]
struct ZKW{
int M;
int k[N<<2],sum[N<<2];
inline void Init(int x){
memset(k,-63,sizeof(k));
for(M=1;M<=x;M<<=1);
FOR(i,1,x)k[M+p(i)]=sum[M+p(i)]=get();
REP(i,M+x,1)sum[i>>1]+=sum[i];
REP(i,M+x,1)k[i>>1]=max(k[i>>1],k[i]);
}
inline void Edit(int x,int v){
k[M+x]=sum[M+x]=v;
x+=M;
while(x)k[x>>1]=max(k[x],k[x^1]),sum[x>>=1]=sum[x<<1]+sum[x<<1|1];
}
inline int Sum(int L,int r){
int ans=0;
for(register int s=M+L-1,t=M+r+1;s^t^1;s>>=1,t>>=1){
if(~s&1)ans+=sum[s^1];
if(t&1)ans+=sum[t^1];
}return ans;
}
inline int Max(int L,int r){
int ans=-1e8;
for(register int s=M+L-1,t=M+r+1;s^t^1;s>>=1,t>>=1){
if(~s&1)ans=max(ans,k[s^1]);
if(t&1)ans=max(ans,k[t^1]);
}return ans;
}
}t;
inline void GETSUM(int x,int y){
int t1=top(x),t2=top(y);
int ans=0;
while(t1!=t2){
if(dep(t1)<dep(t2))swap(x,y),swap(t1,t2);
ans+=t.Sum(p(t1),p(x));
x=g.fa[t1];t1=top(x);
}if(dep(x)>dep(y))swap(x,y);
cout<<ans+t.Sum(p(x),p(y))<<"\n";
}
inline void GETMAX(int x,int y){
int t1=top(x),t2=top(y);
int ans=-1e8;
while(t1!=t2){
if(dep(t1)<dep(t2))swap(x,y),swap(t1,t2);
ans=max(ans,t.Max(p(t1),p(x)));
x=g.fa[t1];t1=top(x);
}if(dep(x)>dep(y))swap(x,y);
cout<<max(ans,t.Max(p(x),p(y)))<<"\n";
}
int main(){
g.init();
g.dfs1(1,g.fa[1]=0,g.dep[1]=1);
g.dfs2(1,1);
t.Init(cnt);
scanf("%d",&m);
FOR(i,1,m){
char op[17];int x,y;
scanf("%s%d%d",op+1,&x,&y);
if(op[2]=='H')t.Edit(g.p[x],y);
else if(op[2]=='S')GETSUM(x,y);
else GETMAX(x,y);
}return 0;
}