给定一棵 n 个节点的树,根节点是1,每个点有一个点权 vi 。初始所有点都是白点。
有 m 个操作:
Data Constraint
n≤100000,m≤200000
考虑单独计算每个点对其他点的贡献。
对于一个修改操作 x ,首先 x 显然会对子树内的所有点造成贡献,如果 x 子树内之前没有黑点,那么 x 还要对父亲的其他子树造成贡献。
所以线段树维护答案,做区间修改操作即可。
时间复杂度: O(nlogn)
#include
#include
#include
#include
#include
using namespace std ;
#define N 100000 + 10
struct Tree {
int val , tag ;
} T[4*N] ;
bool Exist[N] ;
int Node[2*N] , Next[2*N] , Head[N] , tot ;
int W[N] , fa[N] , DFN[N] , R[N] ;
int n , m , Cnt , ret ;
void link( int u , int v ) {
Node[++tot] = v ;
Next[tot] = Head[u] ;
Head[u] = tot ;
}
void DFS( int x ) {
DFN[x] = R[x] = ++ Cnt ;
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == fa[x] ) continue ;
fa[Node[p]] = x ;
DFS( Node[p] ) ;
R[x] = R[Node[p]] ;
}
}
void Update( int v ) {
if ( T[v].tag <= 0 ) return ;
int ls = v + v , rs = v + v + 1 ;
T[ls].val = max( T[ls].val , T[v].tag ) ;
T[rs].val = max( T[rs].val , T[v].tag ) ;
T[ls].tag = max( T[ls].tag , T[v].tag ) ;
T[rs].tag = max( T[rs].tag , T[v].tag ) ;
T[v].tag = 0 ;
}
void Modify( int v , int l , int r , int x , int y , int value ) {
if ( x > y ) return ;
if ( l == x && r == y ) {
T[v].val = max( T[v].val , value ) ;
T[v].tag = max( T[v].tag , value ) ;
return ;
}
Update( v ) ;
int mid = (l + r) / 2 ;
if ( y <= mid ) Modify( v + v , l , mid , x , y , value ) ;
else if ( x > mid ) Modify( v + v + 1 , mid + 1 , r , x , y , value ) ;
else {
Modify( v + v , l , mid , x , mid , value ) ;
Modify( v + v + 1 , mid + 1 , r , mid + 1 , y , value ) ;
}
T[v].val = max( T[v+v].val , T[v+v+1].val ) ;
}
void Search( int v , int l , int r , int x ) {
if ( l == x && r == x ) {
ret = T[v].val ;
return ;
}
Update( v ) ;
int mid = (l + r) / 2 ;
if ( x <= mid ) Search( v + v , l , mid , x ) ;
else Search( v + v + 1 , mid + 1 , r , x ) ;
T[v].val = max( T[v+v].val , T[v+v+1].val ) ;
}
int main() {
freopen( "lca.in" , "r" , stdin ) ;
freopen( "lca.out" , "w" , stdout ) ;
scanf( "%d%d" , &n , &m ) ;
for (int i = 1 ; i <= n ; i ++ ) scanf( "%d" , &W[i] ) ;
for (int i = 1 ; i < n ; i ++ ) {
int u , v ;
scanf( "%d%d" , &u , &v ) ;
link( u , v ) ;
link( v , u ) ;
}
DFS( 1 ) ;
memset( T , -1 , sizeof(T) ) ;
for (int i = 1 ; i <= m ; i ++ ) {
char op[10] ;
scanf( "%s" , op + 1 ) ;
if ( op[1] == 'M' ) {
int x ;
scanf( "%d" , &x ) ;
Modify( 1 , 1 , n , DFN[x] , R[x] , W[x] ) ;
if ( Exist[x] ) continue ;
Exist[x] = 1 ;
while ( fa[x] ) {
int y = fa[x] ;
Modify( 1 , 1 , n , DFN[y] , DFN[x] - 1 , W[y] ) ;
Modify( 1 , 1 , n , R[x] + 1 , R[y] , W[y] ) ;
if ( Exist[y] ) break ;
Exist[y] = 1 ;
x = y ;
}
} else {
int x ;
scanf( "%d" , &x ) ;
ret = -1 ;
Search( 1 , 1 , n , DFN[x] ) ;
printf( "%d\n" , ret ) ;
}
}
}
以上.