说在前面
开始无脑码起了代码emmm
题目
题目大意
给出一个有 n n 个节点的树,每个节点有颜色(黑或白)和权值,现在需要支持以下三个操作:
- :询问 u u 点所在的同色联通块的最大值
- :将 u u 的颜色取反
- :将节点
u
u
的权值改为
范围:操作总次数 m≤105 m ≤ 10 5 , n≤105 n ≤ 10 5 ,点权 |w|≤109 | w | ≤ 10 9
输入输出格式
输入格式:
第一行一个整数 n n ,表示节点个数
接下来 行,每行两个整数 u,v u , v 描述一条树边
接下来两行,每行 n n 个整数,第一行颜色,第二行权值接下来一个整数 ,表示操作次数
最后 m m 行,每行一个操作,格式如题输出格式:
对于每一个询问操作,输出一行一个整数表示答案
解法
这道题和 QTREE6 差不多
在 QTREE6 中,维护的信息是 虚子树大小以及链上大小
这道题维护的是 虚子树的最大值以及链上最大值,虚子树最大值用set即可查询set最大值时,调用begin()/end()是 的
只有在虚实子树转变的时候,才需要插入/删除,也就是说Access的均摊变成了 log22n log 2 2 n ,复杂度是ok的
下面是代码
注意改权值操作,两棵树里都得改
一开始me只改了一棵树里的,WA了几发#include <set> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; int N , M , tp , head[100005] ; int fa[100005] , col[100005] , val[100005] ; struct Path{ int pre , to ; } p[200005] ; struct Comp{ bool operator () ( const int &A , const int &B ){ return A > B ; } } ; template < typename T > void smax( T &A , T B ){ if( A < B ) A = B ; } struct Node{ Node *ch[2] , *fa ; set<int,Comp> imax ; int rmax , cur ; int getMax(){ return max( rmax , *( imax.begin() ) ) ; } void update(){ rmax = cur ; if( ch[0] ) smax( rmax , ch[0]->getMax() ) ; if( ch[1] ) smax( rmax , ch[1]->getMax() ) ; } } ; struct LCT{ Node w[100005] ; void init(){ for( int i = 1 ; i <= N ; i ++ ){ w[i].ch[0] = w[i].ch[1] = w[i].fa = NULL ; w[i].cur = w[i].rmax = val[i] ; w[i].imax.clear() , w[i].imax.insert( -1234567890 ) ; } } bool isRoot( Node *nd ){ if( !nd->fa ) return true ; return nd->fa->ch[0] != nd && nd->fa->ch[1] != nd ; } void Rotate( Node *nd , int k ){ Node *x = nd->ch[k] ; if( !isRoot( nd ) ){ if( nd->fa->ch[0] == nd ) nd->fa->ch[0] = x ; else nd->fa->ch[1] = x ; } x->fa = nd->fa ; if( x->ch[k^1] ) x->ch[k^1]->fa = nd ; nd->ch[k] = x->ch[k^1] ; x->ch[k^1] = nd , nd->fa = x ; nd->update() , x->update() ; } void Splay( Node *nd ){ // pushdown here while( !isRoot( nd ) ){ Node *fa = nd->fa , *gdfa = fa->fa ; int pn = ( fa->ch[1] == nd ) , pf ; if( !isRoot( fa ) ){ pf = ( gdfa->ch[1] == fa ) ; if( pn == pf ) swap( fa , gdfa ) ; Rotate( fa , pn ) , Rotate( gdfa , pf ) ; } else Rotate( fa , pn ) ; } } void Access( Node *nd ){ Node *tmp = NULL ; while( nd ){ Splay( nd ) ; if( tmp ) nd->imax.erase( tmp->getMax() ) ; if( nd->ch[1] ) nd->imax.insert( nd->ch[1]->getMax() ) ; nd->ch[1] = tmp ; nd->update() ; tmp = nd , nd = nd->fa ; } } void link( int x , int y ){ if( !y ) return ; Node *u = ( w + x ) , *v = ( w + y ) ; // link u to v Access( v ) , Splay( v ) , Splay( u ) ; u->fa = v , v->imax.insert( u->getMax() ) ; } void cut( int x , int y ){ if( !y ) return ; Node *u = ( w + x ) , *v = ( w + y ) ;// cut u from v Access( v ) , Splay( v ) , Splay( u ) ; v->imax.erase( u->getMax() ) , u->fa = NULL ; } Node *getLeft( Node *nd ){ while( nd->ch[0] ) nd = nd->ch[0] ; return nd ; } int Query( int x ){ Node *u = ( w + x ) , *tmp , *t2 ; Access( u ) , Splay( u ) ; tmp = getLeft( u ) , Splay( tmp ) ; if( col[ tmp - w ] != col[x] ){ Access( t2 = getLeft( tmp->ch[1] ) ) , Splay( tmp ) ; return t2->getMax() ; } else return tmp->getMax() ; } void change( int x , int w ){ Node *u = ( this->w + x ) ; Access( u ) , Splay( u ) ; u->cur = w , u->update() ; } } Tree[2] ; void In( int t1 , int t2 ){ p[++tp] = ( Path ){ head[t1] , t2 } ; head[t1] = tp ; p[++tp] = ( Path ){ head[t2] , t1 } ; head[t2] = tp ; } void dfs( int u , int f ){ for( int i = head[u] ; i ; i = p[i].pre ){ int v = p[i].to ; if( v == f ) continue ; Tree[ col[v] ].link( v , u ) ; fa[v] = u , dfs( v , u ) ; } } void solve(){ scanf( "%d" , &M ) ; for( int i = 1 , opt , u , w ; i <= M ; i ++ ){ scanf( "%d%d" , &opt , &u ) ; if( opt == 2 ){ // change val scanf( "%d" , &w ) ; Tree[0].change( u , w ) , Tree[1].change( u , w ) ; } else if( opt == 1 ){ //change col Tree[ col[u] ].cut( u , fa[u] ) ; col[u] ^= 1 , Tree[ col[u] ].link( u , fa[u] ) ; } else printf( "%d\n" , Tree[ col[u] ].Query( u ) ) ; } } int main(){ scanf( "%d" , &N ) ; for( int i = 1 , u , v ; i < N ; i ++ ) scanf( "%d%d" , &u , &v ) , In( u , v ) ; for( int i = 1 ; i <= N ; i ++ ) scanf( "%d" , &col[i] ) ; for( int i = 1 ; i <= N ; i ++ ) scanf( "%d" , &val[i] ) ; Tree[0].init() , Tree[1].init() ; dfs( 1 , 1 ) ; solve() ; }