这个题目就是树剖的板子题(比板子还裸)
于是就直接上了QAQ
还是先扯一下树剖吧
fa[x]:x在树中的父亲
dep[x]:x在树中的深度
size[x]:x的子树结点数(子树大小)
son[x]:x的重儿子,即u→son[u]为重边
top[x]:x所在重路径的顶部结点(深度最小)
seg[x]:x在线段树中的位置(下标) (但是我一直发疯打的seq)
rev[x]:线段树中第x个位置对应的树中结点编号,即rev[seg[x]]=x
对于前四个,我们一遍DFS即可,后三个数组我们再用一遍DFS也求了出来
于是就可以欢快的套上线段树维护了
其实树剖码量挺大的
当年弱,调程序调到死
丑陋的代码:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define FOR(i,n,m) for(int i=n;i<=m;++i)
#define FR(i,n,m) for(int i=n;i>=m;--i)
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define re register
#define gc getchar()
using namespace std;
const int N=100010,INF=2139062143;
inline int read() {
re int x(0),f(1);
re char ch=gc;
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=gc;
}
while(ch>='0'&&ch<='9') {
x=(x<<1)+(x<<3)+(ch^48);
ch=gc;
}
return x*f;
}
int size[N],fa[N],deep[N],son[N];
struct edge {
int next,to;
}e[N];
int h[N],cnt;
inline void add(int u,int v) {
e[++cnt]=(edge) {h[u],v};
h[u]=cnt;
}
#define QXX(u) for(int v,i=h[u];v=e[i].to,i;i=e[i].next)
bool vis[N];
void dfs1(int now) {
vis[now]=1;
size[now]=1;
QXX(now) if(v!=fa[now]&&!vis[v]) {
deep[v]=deep[now]+1;
fa[v]=now;
dfs1(v);
size[now]+=size[v];
if(size[v]>size[son[now]]) son[now]=v;
}
}
int seq[N],rev[N],top[N];
void dfs2(int now) {
if(son[now]) {
top[son[now]]=top[now];
seq[son[now]]=++seq[0];
rev[seq[0]]=son[now];
dfs2(son[now]);
}
QXX(now) if(!top[v]) {
if(v!=son[now]) {
top[v]=v;
seq[v]=++seq[0];
rev[seq[0]]=v;
dfs2(v);
}
}
}
struct node {
int _max,sum;
}a[N];
#define ls id<<1
#define rs id<<1|1
int num[N];
inline void update(int id) {
a[id].sum=a[ls].sum+a[rs].sum;
a[id]._max=max(a[ls]._max,a[rs]._max);
}
inline void built(int l,int r,int id) {
if(l==r) {
a[id]._max=a[id].sum=num[rev[l]];
return;
}
int mid=(l+r)>>1;
built(l,mid,ls);
built(mid+1,r,rs);
update(id);
}
inline void revise(int id,int l,int r,int k,int val) {
if(l>k||r<k) return;
if(l==r&&l==k) {
a[id].sum=val;
a[id]._max=val;
return;
}
int mid=(l+r)>>1;
if(mid>=k) revise(ls,l,mid,k,val);
else revise(rs,mid+1,r,k,val);
update(id);
}
int sum,_max;
inline void query(int id,int l,int r,int x,int y) {
if(x>r||y<l) return;
if(l>=x&&r<=y) {
sum+=a[id].sum;
_max=max(_max,a[id]._max);
return;
}
int mid=(l+r)>>1;
if(mid>=x) query(ls,l,mid,x,y);
if(mid<y) query(rs,mid+1,r,x,y);
}
inline void ask(int x,int y) {
int tx=top[x],ty=top[y];
while(tx!=ty) {
if(deep[tx]<deep[ty]) swap(tx,ty),swap(x,y);
query(1,1,seq[0],seq[tx],seq[x]);
x=fa[tx],tx=top[x];
}
if(deep[x]>deep[y]) swap(x,y);
query(1,1,seq[0],seq[x],seq[y]);
}
int main() {
int n=read();
FOR(i,1,n-1) {
int x=read(),y=read();
add(x,y),add(y,x);
}
FOR(i,1,n) num[i]=read();
dfs1(1);
seq[0]=seq[1]=top[1]=rev[1]=1;
dfs2(1);
built(1,seq[0],1);
int Q=read();
while(Q--) {
string ss;
cin>>ss;
if(ss[0]=='C') {
int x=read(),y=read();
revise(1,1,seq[0],seq[x],y);
}
else {
int x=read(),y=read();
_max=-0x3f3f3f3f,sum=0;
ask(x,y);
if(ss[1]=='S') cout<<sum<<endl;
else cout<<_max<<endl;
}
}
return 0;
}