洛谷 P2590
#include<bits/stdc++.h>
using namespace std;
#define maxn 5000005
#define inf 900000005
#define ll long long
struct node
{
int l,r;
int sum;
int minn,maxx;
int lazy;
}tree[maxn<<2];
struct node2
{
int to;
int next;
}edge[maxn<<1];
int cnt,head[maxn];
inline void add(int u,int v)
{
edge[++cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt;
}
int dep[maxn];
int fa[maxn];
int son[maxn];
int siz[maxn];
int top[maxn];
int nid[maxn];
int nw[maxn];
int w[maxn];
int pos;
inline void DFS1(int now,int fath)
{
fa[now] = fath;
siz[now] = 1;son[now] = 0;
dep[now] = dep[fath] + 1;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to==fath)
continue;
DFS1(edge[i].to,now);
siz[now] += siz[edge[i].to];
if(siz[son[now]]<siz[edge[i].to])
son[now] = edge[i].to;
}
}
inline void DFS2(int now,int topx)
{
top[now] = topx;
nid[now] = ++pos;
nw[pos] = w[now];
if(son[now])
DFS2(son[now],topx);
else
return;
for(int i=head[now];i;i=edge[i].next)
{
if(edge[i].to!=fa[now]&&edge[i].to!=son[now])
DFS2(edge[i].to,edge[i].to);
}
}
inline void push_up(int x)
{
int l = x<<1;
int r = x<<1|1;
tree[x].sum = tree[l].sum + tree[r].sum;
tree[x].minn = min(tree[l].minn,tree[r].minn);
tree[x].maxx = max(tree[l].maxx,tree[r].maxx);
}
void build(int x,int l,int r)
{
tree[x].lazy = 0;
tree[x].minn = tree[x].maxx = 0;
tree[x].l = l;
tree[x].r = r;
if(l==r)
{
tree[x].sum = nw[l];
tree[x].maxx = nw[l];
tree[x].minn = nw[l];
return;
}
int mid = (l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_up(x);
return;
}
inline void tree_change(int x,int l,int r,int q,int v)
{
if(l==r)
{
tree[x].sum = tree[x].maxx = tree[x].minn = v;
return;
}
int mid = (l+r)>>1;
if(q<=mid) tree_change(x<<1,l,mid,q,v);
else tree_change(x<<1|1,mid+1,r,q,v);
push_up(x);
}
inline int querysum(int x,int l,int r)
{
int ans = 0;
if(l<=tree[x].l&&r>=tree[x].r)
{
return tree[x].sum;
}
int mid = (tree[x].l+tree[x].r)>>1;
if(l<=mid) ans += querysum(x<<1,l,r);
if(r>mid) ans += querysum(x<<1|1,l,r);
return ans;
}
inline int querymax(int x,int l,int r)
{
int ans = -inf;
if(l<=tree[x].l&&r>=tree[x].r) return tree[x].maxx;
int mid = (tree[x].l+tree[x].r)>>1;
if(l<=mid) ans = max(querymax(x<<1,l,r),ans);
if(r>mid) ans = max(querymax(x<<1|1,l,r),ans);
return ans;
}
inline int querymin(int x,int l,int r)
{
int ans = inf;
if(l<=tree[x].l&&r>=tree[x].r) return tree[x].minn;
int mid = (tree[x].l+tree[x].r)>>1;
if(l<=mid) ans = min(querymin(x<<1,l,r),ans);
if(r>mid) ans = min(querymin(x<<1|1,l,r),ans);
return ans;
}
inline int tree_sum(int u,int v)
{
int ans = 0;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
ans += querysum(1,nid[top[u]],nid[u]);
u = fa[top[u]];
}
if(dep[u]>dep[v])
swap(u,v);
ans += querysum(1,nid[u],nid[v]);
return ans;
}
inline int tree_max(int u,int v)
{
int ans = -inf;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
ans = max(ans,querymax(1,nid[top[u]],nid[u]));
u = fa[top[u]];
}
if(dep[u]>dep[v])
swap(u,v);
ans = max(ans,querymax(1,nid[u],nid[v]));
return ans;
}
inline int tree_min(int u,int v)
{
int ans = inf;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])
swap(u,v);
ans = min(ans,querymin(1,nid[top[u]],nid[u]));
u = fa[top[u]];
}
if(dep[u]>dep[v])
swap(u,v);
ans = min(ans,querymin(1,nid[u],nid[v]));
return ans;
}
int main()
{
int n,m;
cin>>n;
for(int i=1;i<n;++i)
{
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
for(int i=1;i<=n;++i) cin>>w[i];
DFS1(1,0);
DFS2(1,1);
build(1,1,n);
cin>>m;
while(m--)
{
char cxk[10];
cin>>cxk;
int x,y;
cin>>x>>y;
if(cxk[1]=='H')
{
tree_change(1,1,n,nid[x],y);
}
else if(cxk[1]=='M')
{
printf("%d\n",tree_max(x,y));
}
else if(cxk[1]=='S')
{
printf("%d\n",tree_sum(x,y));
}
}
return 0;
}