bzoj 1036 Tree Count

时间:2023-03-09 18:33:37
bzoj 1036 Tree Count

题目大意:给出一棵树,每个点有一个权值,要求三种操作:1.修改某个点的权值,2.询问x到y路径上各点的权值最大值,3.询问x到y路径上各点的权值之和。

 #include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 30010
#define ls o<<1
#define rs o<<1|1
#define define_m int m=(l+r)>>1 int first[N] , k;
struct Edge{
int y , next;
}e[N<<]; void add_edge(int x , int y)
{
e[k].y = y , e[k].next = first[x];
first[x] = k++;
} int sz[N] , dep[N] , fa[N] , son[N] , top[N] , id[N] , num;
void dfs(int u , int f , int d)
{
fa[u] = f , sz[u] = , dep[u]= d , son[u]=;
int mx = ;
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(v == f) continue;
dfs(v , u , d+);
sz[u]+=sz[v];
if(sz[v]>mx) mx=sz[v] , son[u]=v;
}
} void dfs1(int u , int f , int head)
{
top[u]=head , id[u]=++num;
if(son[u]) dfs1(son[u] , u , head);
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
if(v == f || v == son[u]) continue;
dfs1(v , u , v);
}
} int sum[N<<] , mx[N<<] , val[N];
void push_up(int o)
{
sum[o] = sum[ls]+sum[rs];
mx[o] = max(mx[ls] , mx[rs]);
} void build(int o , int l , int r)
{
if(l==r){
sum[o]=mx[o]=val[l];
return ;
}
define_m;
build(ls , l , m);
build(rs , m+ , r);
push_up(o);
} void update(int o , int l , int r , int p , int v)
{
if(l==r){
sum[o]=mx[o]=v;
return;
}
define_m;
if(m>=p) update(ls , l , m , p , v);
else update(rs , m+ , r , p , v);
push_up(o);
} int qSum(int o , int l , int r , int s , int t)
{
if(l>=s && r<=t) return sum[o];
define_m;
int res = ;
if(m>=s) res+=qSum(ls , l , m , s , t);
if(m<t) res+=qSum(rs , m+ , r , s , t);
return res;
} int qMax(int o , int l , int r , int s , int t)
{
if(l>=s && r<=t) return mx[o];
define_m;
int res = -1e9;
if(m>=s) res = max(res , qMax(ls , l , m , s , t));
if(m<t) res = max(res , qMax(rs , m+ , r , s , t));
return res;
} int calPath(int u , int v , int flag)
{
int top1 = top[u] , top2 = top[v] , ret=-1e9;
if(flag) ret=;
while(top1!=top2){
if(dep[top1]<dep[top2]){
swap(top1 , top2);
swap(u , v);
}
if(flag) ret+=qSum( , , num , id[top1] , id[u]);
else ret=max(ret , qMax(,,num,id[top1] , id[u]));
u = fa[top1];
top1 = top[u];
}
if(dep[u]<dep[v]) swap(u,v);
if(flag) ret+=qSum(,,num,id[v],id[u]);
else ret=max(ret , qMax(,,num,id[v],id[u]));
return ret;
}
char str[];
int main()
{
//freopen("in.txt" , "r" , stdin);
int n , x , y , q;
while(scanf("%d" , &n)!=EOF)
{
memset(first , - , sizeof(first));
k = ;
for(int i= ; i<n ; i++){
scanf("%d%d" , &x , &y);
add_edge(x , y);
add_edge(y , x);
}
dfs( , , );
num = ;
dfs1( , , );
int tmp[N];
for(int i= ; i<=n ; i++) scanf("%d" , val+i) , tmp[i]=val[i];
for(int i= ; i<=n ; i++) val[id[i]]=tmp[i];
build( , , num);
// for(int i=1 ; i<=7 ; i++) cout<<i<<" "<<mx[i]<<" "<<sum[i]<<endl;
scanf("%d" , &q);
while(q--){
scanf("%s%d%d", str , &x , &y);
if(str[]=='C'){
update( , , num , id[x] , y);
}
else if(str[]=='M'){
int ret = calPath(x , y , );
printf("%d\n" , ret);
}else{
int ret = calPath(x , y , );
printf("%d\n" , ret);
}
}
}
return ;
}