感觉自己理解的很不透彻
很多东西的定义想半天…
最后还是看着大师的代码才调过的…
BZOJ5210传送门
大师博客传送门
看题可戳传送门
这里并不准备写什么解法,大师博客写的其实挺清楚的…没看懂就多读几遍多想想
就这道题,me感觉需要把维护的东西想清楚…
重链上的信息直接用 线段树维护 ,实际的答案并没有存下来,需要Query得到
虚边的信息上传,上传的是整条链所代表的子树的信息。有一个点发生变化,贡献就会发生变化,就需要撤销掉之前的贡献,然后换上新的。因为贡献并没有存下来,所以需要通过 Query 得到
初始状态可以在树剖的时候顺便dp一发,然后把dp得到的信息,以一种合适的方式放到线段树上
或者也可以是把所有点初始为0,然后往空树里面一个一个赋值。当然这一步也是需要补全权值为0时的信息的,只不过省去了手动dp的步骤
反正要想清楚…
#include
#include
#include
#include
#include
#include
#define QL Query( nd->ch[0] , lf , mid , L , R )
#define QR Query( nd->ch[1] , mid+1,rg , L , R )
using namespace std ;
int N , M , val[200005] , head[200005] , tp ;
long long g[200005] , f[200005] ;
struct Path{
int pre , to ;
} p[400005] ;
struct HEap{
priority_queue<long long,vector<long long>,less<long long> > hp , del ;
void insert( long long x ){ hp.push( x ) ; }
void erase( long long x ){ del.push( x ) ; }
long long top(){
while( !del.empty() && hp.top() == del.top() )
hp.pop() , del.pop() ;
return hp.empty() ? 0 : hp.top() ;
}
} hp[200005] ;
struct Node{
Node *ch[2] ;
long long Lmax , Rmax , mx , sum ;
void update(){
Lmax = max( ch[0]->Lmax , ch[0]->sum + ch[1]->Lmax ) ;
Rmax = max( ch[0]->Rmax + ch[1]->sum , ch[1]->Rmax ) ;
mx = max( ch[0]->Rmax + ch[1]->Lmax , max( ch[0]->mx , ch[1]->mx ) ) ;
sum = ch[0]->sum + ch[1]->sum ;
}
friend Node Merge( Node L , Node R ){
Node rt ;
rt.Lmax = max( L.Lmax , L.sum + R.Lmax ) ;
rt.Rmax = max( L.Rmax + R.sum , R.Rmax ) ;
rt.mx = max( L.Rmax + R.Lmax , max( L.mx , R.mx ) ) ;
rt.sum = L.sum + R.sum ; return rt ;
}
} *root , w[400005] , *tw = w ;
void In( int t1 , int t2 ){
p[++tp] = ( Path ){ head[t1] , t2 } ; head[t1] = tp ;
p[++tp] = ( Path ){ head[t2] , t1 } ; head[t2] = tp ;
}
int dep[200005] , fa[200005] , son[200005] , siz[200005] ;
int in[200005] , top[200005] , arc[200005] , dfs_c , bot[200005] ;
void dfs1( int u ){
for( int i = head[u] ; i ; i = p[i].pre ){
int v = p[i].to ;
if( v == fa[u] ) continue ;
fa[v] = u , dep[v] = dep[u] + 1 ;
dfs1( v ) , siz[u] += siz[v] ;
if( siz[ son[u] ] < siz[v] ) son[u] = v ;
} siz[u] ++ ;
}
long long dfs2( int u , int topp ){
long long now = 0 ;
in[u] = ++dfs_c , arc[ dfs_c ] = u , top[u] = topp ;
if( son[u] ) now = dfs2( son[u] , topp ) , bot[u] = bot[ son[u] ] ;
else bot[u] = u ;
g[u] = val[u] ;
for( int i = head[u] ; i ; i = p[i].pre ){
int v = p[i].to ;
if( v == fa[u] || v == son[u] ) continue ;
hp[u].insert( dfs2( v , v ) ) , g[u] += f[v] ;
} f[u] = max( 0ll , g[u] + f[ son[u] ] ) , now = max( now , max( f[u] , hp[u].top() ) ) ;
return now ;
}
Node *build( int lf , int rg ){
Node *nd = ++tw ;
if( lf == rg ){
int u = arc[lf] ; nd->sum = g[u] ;
nd->Lmax = nd->Rmax = max( 0ll , g[u] ) ;
nd->mx = max( nd->Lmax , hp[u].top() ) ;
return nd ;
} int mid = ( lf + rg ) >> 1 ;
nd->ch[0] = build( lf , mid ) ;
nd->ch[1] = build( mid+1,rg ) ;
nd->update() ; return nd ;
}
void Modify( Node *nd , int lf , int rg , int pos ){
if( lf == rg ){
int u = arc[lf] ; nd->sum = g[u] ;
nd->Lmax = nd->Rmax = max( 0ll , g[u] ) ;
nd->mx = max( nd->Lmax , hp[u].top() ) ; return ;
} int mid = ( lf + rg ) >> 1 ;
if( mid >= pos ) Modify( nd->ch[0] , lf , mid , pos ) ;
else Modify( nd->ch[1] , mid+1,rg , pos ) ;
nd->update() ;
}
Node Query( Node *nd , int lf , int rg , int L , int R ){
if( L <= lf && rg <= R ) return *nd ;
int mid = ( lf + rg ) >> 1 ;
if( R <= mid ) return QL ;
if( L > mid ) return QR ;
return Merge( QL , QR ) ;
}
void Modify( int u , long long delta ){
Node now , pre , ttt ; bool flag = false ;
while( u ){
ttt = Query( root , 1 , N , in[ top[u] ] , in[ bot[u] ] ) ;
if( flag ) hp[u].erase( pre .mx ) , hp[u].insert( now.mx ) ;
pre = ttt , flag = 1 ;
g[u] += delta , Modify( root , 1 , N , in[u] ) ;
now = Query( root , 1 , N , in[ top[u] ] , in[ bot[u] ] ) ;
delta = now.Lmax - f[ top[u] ] , f[ top[u] ] = now.Lmax ;
u = fa[ top[u] ] ;
}
}
long long Query( int u ){
Node ans = Query( root , 1 , N , in[u] , in[ bot[u] ] ) ;
return ans.mx ;
}
void preWork(){
dfs1( 1 ) ; dfs2( 1 , 1 ) ;
root = build( 1 , N ) ;
}
void solve(){
char opt[10] ;
for( int i = 1 , x , y ; i <= M ; i ++ ){
scanf( "%s%d" , opt , &x ) ;
if( opt[0] == 'M' ){
scanf( "%d" , &y ) ;
Modify( x , y - val[x] ) , val[x] = y ;
} else printf( "%lld\n" , Query( x ) ) ;
}
}
int main(){
scanf( "%d%d" , &N , &M ) ;
for( int i = 1 ; i <= N ; i ++ )
scanf( "%d" , &val[i] ) ;
for( int i = 1 , u , v ; i < N ; i ++ )
scanf( "%d%d" , &u , &v ) , In( u , v ) ;
preWork() ; solve() ;
}