[luogu2590] [ZJOI2008]树的统计
emmm树剖裸题,就线段树维护一下最大值和权值和就行了。
这里有一个点就是:因为会出现负数,所以查最大值的时候不能初始化为0,这样就没法维护负值
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 30005
struct Node {
long long sum,maxx;
}seg[MAXN<<2];
struct edge {
int v,next;
}G[MAXN<<1];
int head[MAXN];
long long val[MAXN],a[MAXN];
int dfn[MAXN],top[MAXN];
int size[MAXN],son[MAXN],fa[MAXN],d[MAXN];
int N,M,tot = 0,num = 0;
#define lson (rt<<1)
#define rson (rt<<1|1)
#define mid ((l+r)>>1)
inline void add(int u,int v) {
G[++tot].v = v;G[tot].next = head[u];head[u] = tot;
}
inline void pushup(int rt) {
seg[rt].sum = seg[lson].sum + seg[rson].sum;
seg[rt].maxx = std::max(seg[lson].maxx,seg[rson].maxx);
}
void Build(int rt,int l,int r) {
if(l==r) {
seg[rt].sum = val[l];
seg[rt].maxx = val[l];
return;
}
Build(lson,l,mid);
Build(rson,mid+1,r);
pushup(rt);
}
void update(int L,long long C,int rt,int l,int r) {
if(l==r&&l==L) {
seg[rt].maxx = C;
seg[rt].sum = C;
return;
}
if(L<=mid) update(L,C,lson,l,mid);
else update(L,C,rson,mid+1,r);
pushup(rt);
}
long long max_query(int L,int R,int rt,int l,int r) {
if(L<=l&&R>=r) return seg[rt].maxx;
if(L>r||R<l) return -30000;
long long maxx = -30000;
if(L<=mid) maxx = std::max(maxx,max_query(L,R,lson,l,mid));
if(R>mid) maxx = std::max(maxx,max_query(L,R,rson,mid+1,r));
return maxx;
}
long long sum_query(int L,int R,int rt,int l,int r) {
if(L<=l&&R>=r) return seg[rt].sum;
if(L>r||R<l) return 0;
long long ans = 0;
if(L<=mid) ans += sum_query(L,R,lson,l,mid);
if(R>mid) ans += sum_query(L,R,rson,mid+1,r);
return ans;
}
void dfs1(int u,int father) {
d[u] = d[father] + 1; fa[u] = father;
son[u] = 0; size[u] = 1;
for(int i=head[u];i;i=G[i].next) {
int v = G[i].v;
if(v==father) continue;
dfs1(v,u);
size[u] += size[v];
if(size[son[u]] < size[v]) son[u] = v;
}
}
void dfs2(int u,int tp) {
dfn[u] = ++num;
top[u] = tp;
val[num] = a[u];
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];i;i=G[i].next) {
int v = G[i].v;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
inline int get_opt() {
int opt;
char ch = getchar();
while(ch!='C'&&ch!='Q') ch = getchar();
if(ch=='C') opt = 1;
else {
ch = getchar();
opt = ch=='M' ? 2 : 3;
}
while((ch=getchar())!=' ');
return opt;
}
long long max_query_cut(int u,int v) {
long long maxx = -30000;
while(top[u]!=top[v]) {
if(d[top[u]]<d[top[v]]) std::swap(u,v);
maxx = std::max(maxx,max_query(dfn[top[u]],dfn[u],1,1,N));
u = fa[top[u]];
}
if(d[u]>d[v]) std::swap(u,v);
maxx = std::max(maxx,max_query(dfn[u],dfn[v],1,1,N));
return maxx;
}
long long sum_query_cut(int u,int v) {
long long ans = 0;
while(top[u]!=top[v]) {
if(d[top[u]]<d[top[v]]) std::swap(u,v);
ans += sum_query(dfn[top[u]],dfn[u],1,1,N);
u = fa[top[u]];
}
if(d[u]>d[v]) std::swap(u,v);
ans += sum_query(dfn[u],dfn[v],1,1,N);
return ans;
}
int main() {
int u,v;
scanf("%d",&N);
for(int i=1;i<N;++i) {
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
for(int i=1;i<=N;++i) scanf("%lld",&a[i]);
d[1] = 0;size[0] = 0;
dfs1(1,1);
dfs2(1,1);
Build(1,1,N);
scanf("%d",&M);
for(int i=1;i<=M;++i) {
int opt = get_opt();
scanf("%d%d",&u,&v);
if(opt==1) update(dfn[u],v,1,1,N);
else if(opt==2) printf("%lld\n",max_query_cut(u,v));
else printf("%lld\n",sum_query_cut(u,v));
}
return 0;
}