一棵树上有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本身
树的统计都是大家学习树链剖分时候的基础模板题。
现在刚学了一下Link_Cut_Tree(动态树的一种),强制把这题在做了做。就像当时用splay来强弄最大值,排序这些题目一样。
都是些基础的询问,不过让我涉及了一下lct的基础知识,只用到access和splay的基本操作。
离掌握lct还有一段路……
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
using namespace std;
const int maxn=30007;
int i,j,k,l,n,m,ans;
int first[maxn*2],next[maxn*2],last[maxn*2],num,lca;
int pfa[maxn],t[maxn][2],key[maxn],mx[maxn],sum[maxn],f[maxn],deep[maxn];
char s[10];
void add(int x,int y){
last[++num]=y;next[num]=first[x];first[x]=num;
last[++num]=x;next[num]=first[y];first[y]=num;
}
void update(int x){
mx[x]=max(key[x],max(mx[t[x][0]],mx[t[x][1]]));
sum[x]=key[x]+sum[t[x][0]]+sum[t[x][1]];
}
bool son(int x){
if(t[f[x]][0]==x)return 0;return 1;
}
void rotate(int x){
int y=f[x],z=son(x);
t[y][z]=t[x][1-z];
if(t[x][1-z])f[t[x][1-z]]=y;f[x]=f[y];
if(f[x])t[f[x]][son(y)]=x;
else pfa[x]=pfa[y],pfa[y]=0;
t[x][1-z]=y;f[y]=x;
update(y);update(x);
}
void splay(int x){
while(f[x]){
if(f[f[x]])if(son(f[x])==son(x))rotate(f[x]);else rotate(x);
rotate(x);
}
}
void access(int x){
int y=0;
while(x){
splay(x);
f[t[x][1]]=0,pfa[t[x][1]]=x;
t[x][1]=y,f[y]=x;
pfa[y]=0;
update(x);
y=x,x=pfa[x];
}lca=y;
}
void build(int x,int y){
access(x);splay(x);pfa[x]=y;
}
void dfs(int x,int y){
int i;deep[x]=deep[y]+1;
rep(i,x)if(last[i]!=y)build(last[i],x),dfs(last[i],x);
}
int main(){
scanf("%d",&n);key[0]=mx[0]=-0x7fffffff;
fo(i,1,n-1)scanf("%d%d",&k,&l),add(k,l);
fo(i,1,n)scanf("%d",&key[i]);
dfs(1,0);
scanf("%d",&m);
fo(i,1,m){
scanf("%s%d%d",s,&k,&l);
if(s[0]=='Q'){
if(k==l){printf("%d\n",key[k]);continue;}
if(deep[k]<deep[l])swap(k,l);
access(k);access(l);splay(k);
if(s[1]=='M'){
ans=mx[k];
if(lca==l)ans=max(ans,key[l]);
else ans=max(ans,max(mx[t[lca][1]],key[lca]));
}
else{
ans=sum[k];
if(lca==l)ans+=key[l];
else ans+=sum[t[lca][1]]+key[lca];
}
printf("%d\n",ans);
}
else{
access(k);key[k]=l;splay(k);update(k);
}
}
}