[BZOJ2329]/[BZOJ2209]-括号修复-Splay维护信息

匿名 (未验证) 提交于 2019-12-03 00:19:01

好久没码过…已经码不动了


BZOJ2329传送门
BZOJ2209传送门
看题可戳传送门,2209是2329的简化版(虽然它们都是省选题)


这个题的难点在于 取反操作 和 翻转操作 的维护
取反操作 和 翻转操作 并不能像普通信息一样直接打tag,因为是不可以直接翻转的,举个例子:
( ( ( ( ) ) 反转变成了 ) ) ) ) ( ( ,如果直接取反显然GG,翻转也类似

原因是,我们在统计贡献的时候,实际采取的策略是:「从左到右,靠左多余右括号不可抵消」。即 ( ( ) ) 这样是可以抵消的,而反转之后的 ) ) ( ( 不行。这导致我们不能直接 反/翻转

但是我们可以发现,反转后的策略,对于原序列的策略是:「从左到右,靠左多余左括号不可抵消」。也就是说,反转之后的答案应该这样维护:原序列如果是 ) ) ( ( 则可以抵消的而 ( ( ) ) 不行。(翻转类似,翻转=反转再交换儿子,所以翻转和反转的策略一样)

那么我们需要维护一些东西,使得在策略发生改变之后,仍然可以得出答案
那么显然的方法就是,两种策略都维护
所以我们只需维护,左边最多连续左括号/右括号,右边最多连续左括号/右括号 即可

注意 反转 和 翻转 以及 覆盖 时的标记细节
然后这题就做完了


me采用的是 左括号-1,右括号+1,统计 lmin/lmax,rmin/rmax 的方式
本质和上面是一样的
(调试语句没有删)

#include <cstdio> #include <cstring> #include <algorithm> using namespace std ;  int N , M ; char s[100005] ; struct Node{     Node *ch[2] , *fa ;     int cur , lmax , rmax , lmin , rmin , siz , tag , sum , id ;     bool frev , finv ;     Node( int x = 0 ): cur( x ) , sum( x ) {         tag = 0 , siz = 1 ;         frev = finv = false ;         lmax = rmax = lmin = rmin = 0 ;         if( x > 0 ) lmax = rmax = 1 ;         if( x < 0 ) lmin = rmin = -1 ;     } ;     void update( ){         siz = ch[0]->siz + 1 + ch[1]->siz ;         sum = ch[0]->sum + cur + ch[1]->sum ;         lmax = max( ch[0]->lmax , ch[0]->sum + cur + ch[1]->lmax ) ;         lmin = min( ch[0]->lmin , ch[0]->sum + cur + ch[1]->lmin ) ;         rmax = max( ch[1]->rmax , ch[0]->rmax + cur + ch[1]->sum ) ;         rmin = min( ch[1]->rmin , ch[0]->rmin + cur + ch[1]->sum ) ;     }     void cover( int x ){         cur = tag = x , sum = x * siz ;         if( x > 0 ) lmax = rmax = sum , lmin = rmin = 0 ;         else lmin = rmin = sum , lmax = rmax = 0 ;         frev = finv = false ;     }     void inv(){         swap( lmax , lmin ) , lmax = -lmax , lmin = -lmin ;         swap( rmax , rmin ) , rmax = -rmax , rmin = -rmin ;         cur = -cur , tag = -tag , sum = -sum ;         finv ^= 1 ;     }     void rev(){         swap( lmax , rmax ) , swap( lmin , rmin ) ;         swap( ch[0] , ch[1] ) , frev ^= 1 ;     }     void pushdown(){         if( ch[0]->fa != ch[0] ){             if( frev ) ch[0]->rev() ;             if( finv ) ch[0]->inv() ;             if( tag ) ch[0]->cover( tag ) ;         } if( ch[1]->fa != ch[1] ){             if( frev ) ch[1]->rev() ;             if( finv ) ch[1]->inv() ;             if( tag ) ch[1]->cover( tag ) ;         } frev = finv = false , tag = 0 ;     } } *root , *sta[100005] , *ans , *null ;  Node *build( int lf , int rg , Node *fa ){     int mid = ( lf + rg ) >> 1 ;     Node *nd = new Node( s[mid] ) ;     nd->ch[0] = nd->ch[1] = null , nd->fa = fa ;     if( lf < mid ) nd->ch[0] = build( lf , mid - 1 , nd ) ;     if( mid < rg ) nd->ch[1] = build( mid + 1 , rg , nd ) ;     nd->update() ; return nd ; }  int d_c , speci ; void dfs( Node *nd ){     if( nd == null ) return ;     nd->pushdown() ;     dfs( nd->ch[0] ) ;     nd->id = d_c ++ ;     dfs( nd->ch[1] ) ; }  void dfs_print( Node *nd ){     if( nd == null ) return ;     printf( "%d(%p) %d --- %d %d\n" , nd->id , nd , nd->fa==null?-1:nd->fa->id , nd->lmax , nd->rmin ) ;     dfs_print( nd->ch[0] ) , dfs_print( nd->ch[1] ) ; }  void Rotate( Node *nd , bool k ){     Node *x = nd->ch[k] ;     if( nd->fa != null ){         if( nd->fa->ch[0] == nd ) nd->fa->ch[0] = x ;         if( nd->fa->ch[1] == nd ) nd->fa->ch[1] = x ;     } x->fa = nd->fa ;     if( x->ch[k^1] != null ) 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 , Node *aim ){     Node *tmp = nd ; int tp = 0 ;     while( tmp != null ) sta[++tp] = tmp , tmp = tmp->fa ;     while( tp ) sta[tp]->pushdown() , tp -- ;      while( nd->fa != aim ){         Node *fa = nd->fa , *gdfa = fa->fa ;         int pn = ( fa->ch[1] == nd ) , pf ;         if( gdfa != aim ){             pf = gdfa->ch[1] == fa ;             if( pn == pf ) swap( gdfa , fa ) ;             Rotate( fa , pn ) , Rotate( gdfa , pf ) ;         } else Rotate( fa , pn ) ;     } if( aim == null ) root = nd ;      if( !speci ) return ;     d_c = 0 , dfs( root ) , dfs_print( root ) ; puts( "spe end" ) ; }  Node *Kth( Node *nd , int K ){     nd->pushdown() ;     int Lsiz = nd->ch[0]->siz ;     if( K == Lsiz + 1 ) return nd ;     if( K <= Lsiz ) return Kth( nd->ch[0] , K ) ;     else return Kth( nd->ch[1] , K - Lsiz - 1 ) ; }  void getInterval( int lf , int rg ){     Node *LF = Kth( root , lf ) , *RG = Kth( root , rg + 2 ) ;     Splay( LF , null ) , Splay( RG , LF ) ; }  void solve(){     char opt[15] , change[5] ;     int illegal_opt = 0 ;     for( int i = 1 , L , R ; i <= M ; i ++ ){         scanf( "%s%d%d" , opt , &L , &R ) ;         if( opt[0] == 'R' ) scanf( "%s" , change ) ;         if( L > R ) { illegal_opt ++ ; continue ; }          getInterval( L , R ) ;         if( opt[0] == 'R' ) root->ch[1]->ch[0]->cover( change[0] == '(' ? -1 : 1 ) ;         else if( opt[0] == 'S' ) root->ch[1]->ch[0]->rev() ;             else if( opt[0] == 'I' ) root->ch[1]->ch[0]->inv() ;         else{             ans = root->ch[1]->ch[0] ;             if( ( R - L + 1 )&1 ){ puts( "-1" ) ; continue ; }              printf( "%d\n" , ( abs( ans->lmax ) + 1 ) / 2 + ( abs( ans->rmin ) + 1 ) / 2 ) ;         }         root->ch[1]->update() , root->update() ;          //d_c = 0 , dfs( root ) ; dfs_print( root ) ; puts( "" ) ;     } }  int main(){     null = new Node( 0 ) ; null->siz = 0 ;     null->ch[0] = null->ch[1] = null->fa = null ;      scanf( "%d%d%s" , &N , &M , s + 1 ) ;     for( int i = 1 ; i <= N ; i ++ )         s[i] = ( s[i] == '(' ? -1 : 1 ) ;     root = build( 0 , N + 1 , null ) ;     solve() ; } 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!