原题:https://www.lydsy.com/JudgeOnline/problem.php?id=1036
题解:这很显然是树链剖分。要求树上路径的和,最大值,单点修改。注意有负数,初值要给成负的最大值
#include<bits/stdc++.h>
#define ls now<<1
#define rs now<<1|1
#define mid (l+r)/2
#define lson ls,l,mid
#define rson rs,mid+1,r
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e5+10;
struct E{
int to,nxt;
}data[N<<1];
int h[N],n,m,q,a[N],len=1,cnt;
int sz[N],f[N],son[N],dep[N];
int id[N],top[N],wt[N];
int sum[N<<2],mm[N<<2];
char s[10];
inline int rd(){
int x=0;int f=1;char s=getchar();
while(!isdigit(s)) f=(s=='-'?-1:f),s=getchar();
while(isdigit(s)) x=(x<<1)+(x<<3)+s-'0',s=getchar();
return x*f;
}
inline void ins(int x,int y){
data[++len].to=y;data[len].nxt=h[x];h[x]=len;
data[++len].to=x;data[len].nxt=h[y];h[y]=len;
}
void dfs1(int x,int fa,int deep){
dep[x]=deep;f[x]=fa;sz[x]=1;
int max_son=-1;
for(int i=h[x];i;i=data[i].nxt){
int y=data[i].to;if(y==fa) continue;
dfs1(y,x,deep+1);
sz[x]+=sz[y];
if(max_son<sz[y]) son[x]=y,max_son=sz[y];
}
}
void dfs2(int x,int tp){
id[x]=++cnt;wt[cnt]=a[x];
top[x]=tp;
if(!son[x]) return ;
dfs2(son[x],tp);
for(int i=h[x];i;i=data[i].nxt){
int y=data[i].to;if(y==f[x] || y==son[x]) continue;
dfs2(y,y);
}
}
inline void upd(int now){
sum[now]=sum[ls]+sum[rs];
mm[now]=max(mm[ls],mm[rs]);
}
void build(int now,int l,int r){
if(l==r){
sum[now]=mm[now]=wt[l];return ;
}
build(lson);
build(rson);
upd(now);
}
int query(int now,int l,int r,int x,int y){
if(x<=l && r<=y){
return sum[now];
}
int ans=0;
if(x<=mid) ans+=query(lson,x,y);
if(mid<y) ans+=query(rson,x,y);
return ans;
}
int qMax(int now,int l,int r,int x,int y){
if(x<=l && r<=y){
return mm[now];
}
int ans=-inf;
if(x<=mid) ans=max(ans,qMax(lson,x,y));
if(mid<y) ans=max(ans,qMax(rson,x,y));
return ans;
}
void change(int now,int l,int r,int x,int c){
if(l==x && r==x){
mm[now]=c;sum[now]=c;return ;
}
if(x<=mid) change(lson,x,c);
if(mid<x) change(rson,x,c);
upd(now);
}
int qRange(int x,int y){
int ans=0;
while(top[x]!=top[y]){//不在一条链上时
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=query(1,1,cnt,id[top[x]],id[x]);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans+=query(1,1,cnt,id[x],id[y]);
return ans;
}
int qRangeM(int x,int y){
int ans=-inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,qMax(1,1,cnt,id[top[x]],id[x]));
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans=max(ans,qMax(1,1,cnt,id[x],id[y]));
return ans;
}
int main(){
// freopen("count.in","r",stdin);
n=rd();
for(int i=1;i<n;i++){
int x=rd();int y=rd();ins(x,y);
}
for(int i=1;i<=n;i++) a[i]=rd();
dfs1(1,0,1);cnt=0;
dfs2(1,1);
memset(mm,-0x3f,sizeof mm);
build(1,1,n);
q=rd();
for(int i=1;i<=q;i++){
scanf("%s",s);int x=rd();int y=rd();
if(s[1]=='H'){
change(1,1,n,id[x],y);
}
if(s[1]=='S') printf("%d\n",qRange(x,y));
if(s[1]=='M') printf("%d\n",qRangeM(x,y));
}
return 0;
}