zoukankan      html  css  js  c++  java
  • [AHOI2017/HNOI2017]单旋

    题目

      点这里看题目。

    分析

      最妙的地方在于,这道题其实是用一种数据结构模拟另一种数据结构
      我们需要维护深度和树的结构,以下对于每个操作进行分别讨论。

    插入一个新节点

      可以发现,这个新节点一定会成为自己的前驱或者后继中深度较大者的儿子
      然后可以更新深度和树的结构。

    单旋最小值

      发现树会有如下的变化:
        如果自己有儿子,那么它只会是自己的右儿子;旋转后,它会接到自己原先的父亲上
        除了自己的儿子以外,其它的节点的深度都会 +1
        
    原先的根变成了最小值的儿子
    根随后变成最小值
      单旋最大值同理分析。

    单旋最小值并删除

      先模拟好单旋的修改,然后考虑旋转后的变化:
        所有节点深度 -1
        
    断开最小值和它的右儿子的边,根变为它的右儿子

      单旋最大值并删除同理分析。

      发现树的深度的修改实际上可以理解为值域上一段区间的加减,因此可以用权值线段树维护;前驱后继也可以顺便用它维护了。
      中途我们需要用 map 来维护树的形态,或者离散化之后直接存下来也可以。
      时间复杂度:(O(nlog_2|V|))

    代码

    #include <map>
    #include <cstdio>
    using namespace std;
    
    const int up = 1e9/*4*/;
    const int MAXN = 1e5 + 5, MAXLOG = 30, MAXS = MAXN * MAXLOG/*205*/;
    
    template<typename _T>
    void read( _T &x )
    {
    	x = 0;char s = getchar();int f = 1;
    	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
    	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
    	x *= f;
    }
    
    template<typename _T>
    void write( _T x )
    {
    	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
    	if( 9 < x ){ write( x / 10 ); }
    	putchar( x % 10 + '0' );
    }
    
    map<int, int> fa, ch[2];
    
    int siz[MAXS], dep[MAXS], tag[MAXS], lch[MAXS], rch[MAXS];
    int tot, rt, sgrt;
    
    void upt( const int x ) { siz[x] = siz[lch[x]] + siz[rch[x]]; }
    void add( const int x, const int v ) { dep[x] += siz[x] * v, tag[x] += v; }
    void normalize( const int x ) { if( tag[x] ) add( lch[x], tag[x] ), add( rch[x], tag[x] ), tag[x] = 0; }
    
    void setNode( int &u, const int l, const int r, const int pos, const int v )
    {
    	if( ! u ) u = ++ tot;
    	if( l == r ) { siz[u] += v; return ; }
    	int mid = l + r >> 1; normalize( u );
    	if( pos <= mid ) setNode( lch[u], l, mid, pos, v );
    	else setNode( rch[u], mid + 1, r, pos, v );
    	upt( u );
    }
    
    void update( int &u, const int l, const int r, const int segL, const int segR, const int v )
    {
    	if( ! u ) u = ++ tot;
    	if( segL <= l && r <= segR ) { add( u, v ); return ; }
    	int mid = l + r >> 1; normalize( u );
    	if( segL <= mid ) update( lch[u], l, mid, segL, segR, v );
    	if( mid < segR ) update( rch[u], mid + 1, r, segL, segR, v );
    	upt( u );
    }
    
    int query( const int u, const int l, const int r, const int segL, const int segR )
    {
    	if( ! u ) return 0;
    	if( segL <= l && r <= segR ) return siz[u];
    	int mid = l + r >> 1, ret = 0; normalize( u );
    	if( segL <= mid ) ret += query( lch[u], l, mid, segL, segR );
    	if( mid < segR ) ret += query( rch[u], mid + 1, r, segL, segR );
    	return ret;
    }
    
    int Kth( const int u, const int l, const int r, const int rnk )
    {
    	if( l == r ) return l;
    	int mid = l + r >> 1; normalize( u );
    	if( rnk <= siz[lch[u]] ) return Kth( lch[u], l, mid, rnk );
    	return Kth( rch[u], mid + 1, r, rnk - siz[lch[u]] );
    }
    
    int getDep( const int u, const int l, const int r, const int pos )
    {
    	if( l == r ) return dep[u];
    	int mid = l + r >> 1; normalize( u );
    	if( pos <= mid ) return getDep( lch[u], l, mid, pos );
    	return getDep( rch[u], mid + 1, r, pos );
    }
    
    int Kth( const int rnk ) { if( rnk <= 0 ) return -1; if( rnk > siz[sgrt] ) return up + 1; return Kth( sgrt, 1, up, rnk ); }
    int getDep( const int id ) { if( id < 0 || id > up ) return -0x3f3f3f3f; return getDep( sgrt, 1, up, id ); }
    
    int getMx( const int u, const int l, const int r )
    {
    	if( l == r ) return l;
    	int mid = l + r >> 1; normalize( u );
    	if( siz[rch[u]] ) return getMx( rch[u], mid + 1, r );
    	return getMx( lch[u], l, mid );
    }
    
    int getMn( const int u, const int l, const int r )
    {
    	if( l == r ) return l;
    	int mid = l + r >> 1; normalize( u );
    	if( siz[lch[u]] ) return getMn( lch[u], l, mid );
    	return getMn( rch[u], mid + 1, r );
    }
    
    int rotMn()
    {
    	int id = getMn( sgrt, 1, up ), rig = ch[1][id], y = fa[id];
    	if( rt == id ) return 1;
    	if( rig ) fa[rig] = y; fa[rt] = id, fa[id] = 0;
    	ch[1][id] = rt, ch[0][y] = rig, rt = id;
    	int ret = getDep( id );
    	update( sgrt, 1, up, y, up, 1 );
    	update( sgrt, 1, up, id, id, -ret + 1 );
    	return ret;
    }
    
    int rotMx()
    {
    	int id = getMx( sgrt, 1, up ), lef = ch[0][id], y = fa[id];
    	if( rt == id ) return 1;
    	if( lef ) fa[lef] = y; fa[rt] = id, fa[id] = 0;
    	ch[0][id] = rt, ch[1][y] = lef, rt = id;
    	int ret = getDep( id );
    	update( sgrt, 1, up, 1, y, 1 );
    	update( sgrt, 1, up, id, id, -ret + 1 );
    	return ret;
    }
    
    int main()
    {
    	int op, k, N;
    	read( N );
    	while( N -- )
    	{
    		read( op );
    		if( op == 1 )
    		{
    			read( k ), setNode( sgrt, 1, up, k, 1 );
    			if( siz[1] == 1 ) 
    			{ 
    				fa[rt = k] = 0, update( sgrt, 1, up, k, k, 1 ); 
    				puts( "1" );
    				continue; 
    			}
    			int rnk = query( sgrt, 1, up, 1, k );
    			int pre = Kth( rnk - 1 ), suf = Kth( rnk + 1 );
    			int dpre = getDep( pre ), dsuf = getDep( suf );
    			if( dpre > dsuf ) fa[k] = pre, ch[1][pre] = k, update( sgrt, 1, up, k, k, dpre + 1 );
    			else fa[k] = suf, ch[0][suf] = k, update( sgrt, 1, up, k, k, dsuf + 1 );
    			write( getDep( k ) ), putchar( '
    ' );
    		}
    		if( op == 2 ) write( rotMn() ), putchar( '
    ' );
    		if( op == 3 ) write( rotMx() ), putchar( '
    ' );
    		if( op == 4 ) 
    		{
    			int ans = rotMn(), tmp = rt, y = ch[1][tmp];
    			update( sgrt, 1, up, tmp + 1, up, -1 );
    			update( sgrt, 1, up, tmp, tmp, - ans );
    			if( y ) fa[y] = 0; ch[1][tmp] = 0, rt = y;
    			setNode( sgrt, 1, up, tmp, -1 );
    			write( ans ), putchar( '
    ' );
    		}
    		if( op == 5 )
    		{
    			int ans = rotMx(), tmp = rt, y = ch[0][tmp];
    			update( sgrt, 1, up, 1, tmp - 1, -1 );
    			update( sgrt, 1, up, tmp, tmp, -ans );
    			if( y ) fa[y] = 0; ch[0][tmp] = 0, rt = y;
    			setNode( sgrt, 1, up, tmp, -1 );
    			write( ans ), putchar( '
    ' );
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java反射研究(3)
    Java反射研究(2)
    Java反射研究(1)
    从百度文库中复制文本的方法
    jdk/bin中的native2ascii.exe使用
    EA经典入门教程
    JSP自定义标签(3)
    JSP自定义标签(1)
    将Java doc转换为chm的方法
    多态性——vptr和vtable
  • 原文地址:https://www.cnblogs.com/crashed/p/13037105.html
Copyright © 2011-2022 走看看