zoj 2112Dynamic Rankings(树状数组套splay)

zoj 2112Dynamic Rankings(树状数组套splay)


线段树套splay消耗空间略大,改成树状数组套splay就可以了。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define lson l , m , rt<<1
#define rson m + 1 , r , rt<<1|1
#define ls son[0][rt]
#define rs son[1][rt]
#define lowbit(x) (x&(-x))
using namespace std ;
 
const int maxn = 50001 ;
const int N = maxn*15 ;
const int INF = 1111111111 ;
int a[maxn] , n , pool[N] , top ;
struct TTT {
    int son[2][N] , size[N] , fa[N] , val[N] ;
    int root[maxn] , tot ;
    void push_up ( int rt ) {
        size[rt] = size[ls] + size[rs] + 1 ;
    }
    int new_node ( int _val ) {
        int rt ;
        if ( top ) rt = pool[top--] ;
        else rt = ++tot ;
        size[rt] = 1 ;
        ls = rs = fa[rt] = 0 ;
        val[rt] = _val ;
        return rt ;
    }
    void build_root ( int rt ) {
        rs = new_node ( INF ) ;
        fa[rs] = rt ;
    }
    void build ( int l , int r , int rt ) {
        root[rt] = new_node(-INF) ;
        build_root ( root[rt] ) ;
        if ( l == r ) return ;
        int m = l + r >> 1 ;
        build ( lson ) ;
        build ( rson ) ;
    }
    void rot ( int rt ) {
        int y = fa[rt] , z = fa[y] , c = rt == son[0][y] ;
        son[!c][y] = son[c][rt] , fa[son[c][rt]] = y ;
        son[c][rt] = y , fa[y] = rt ;
        fa[rt] = z ;
        son[y==son[1][z]][z] = rt ;
        push_up ( y ) ;
    }
    void splay ( int rt , int to ) {
        while ( fa[rt] != to ) {
            int y = fa[rt] , z = fa[y] ;
            if ( z != to ) rot ( (rt==son[0][y])^(y==son[0][z]) ? rt : y ) ;
            rot ( rt ) ;
        }
        push_up ( rt ) ;
    }
    int find_smaller ( int rt , int v ) {
        int ret ;
        if ( val[rt] >= v ) {
            if ( !ls ) return rt ;
            ret = find_smaller ( ls , v ) ;
        } else {
            if ( !rs ) return rt ;
            ret = find_smaller ( rs , v ) ;
            if ( val[ret] >= v ) ret = rt ;
        }
        return ret ;
    }
    int find_left_most ( int rt ) {
        while ( ls ) rt = ls ;
        return rt ;
    }
    int count_smaller ( int rt , int v ) {
        if ( !rt ) return 0 ;
        if ( val[rt] < v ) return size[ls] + 1 + count_smaller ( rs , v ) ;
        else return count_smaller ( ls , v ) ;
    }
    void add ( int& rt , int v ) {
        rt = find_smaller ( rt , v ) ;
        splay ( rt , 0 ) ;
        int temp = find_left_most ( rs ) ;
        splay ( temp , rt ) ;
        son[0][temp] = new_node ( v ) ;
        fa[son[0][temp]] = temp ;
        push_up ( temp ) ; push_up ( rt ) ;
    }
    void print ( int rt ) {
        if ( !rt ) return ;
        printf ( "rt = %d , sz = %d\n" , rt , size[rt] ) ;
        printf ( "ls = %d , rs = %d , fa = %d , val = %d\n" , ls , rs , fa[rt] , val[rt] ) ;
        print ( ls ) ;
        print ( rs ) ;
    }
    void del ( int& rt , int v ) {
        rt = find_smaller ( rt , v ) ;
        splay ( rt , 0 ) ;
        int temp = find_left_most ( rs ) ;
        if ( val[temp] != v ) return ;
        splay ( temp , rt ) ;
        temp = find_left_most ( son[1][temp] ) ;
        splay ( temp , rt ) ;
        pool[++top] = son[0][temp] ;
        son[0][temp] = 0 ;
        push_up ( temp ) ; push_up ( rt ) ;
    }
    void update ( int pos , int v , int op ) {
		while ( pos <= n ) {
			if ( op == 0 ) add ( root[pos] , v ) ;
			else del ( root[pos] , v ) ;
			pos += lowbit ( pos ) ;
		}
    }
    int count ( int a , int b , int v ) {
		int suma = 0 , sumb = 0 ;
		int pos = a - 1 ;
		while ( pos ) {
			suma += count_smaller ( root[pos] , v ) - 1 ;
			pos -= lowbit(pos) ;
		}
		pos = b ;
		while ( pos ) {
			sumb += count_smaller ( root[pos] , v ) - 1 ;
			pos -= lowbit(pos) ;
		}
        return sumb-suma ;
    }
    void init () {
        tot = 0 ;
        top = 0 ;
		for ( int i = 1 ; i <= n ; i ++ ) {
			root[i] = new_node ( -INF ) ;
			build_root ( root[i] ) ;
		}
        for ( int i = 1 ; i <= n ; i ++ ) {
    //      printf ( "a[%d] = %d\n" , i , a[i] ) ;
            update ( i , a[i] , 0 ) ;
        }
    }
    int ask ( int a , int b , int k ) {
        int l = 0 , r = 1000000000 ;
        while ( l <= r ) {
            int m = l + r >> 1 ;
            int cnt = count ( a , b , m ) ;
//          printf ( "m = %d , cnt = %d\n" , m , cnt ) ;
            if ( cnt <= k - 1 ) l = m + 1 ;
            else r = m - 1 ;
//          printf ( "l = %d , r = %d\n" , l , r ) ;
        }
        return r ;
    }
    void modify ( int pos , int num ) {
        update ( pos , a[pos] , 1 ) ;
        update ( pos , num , 0 ) ;
        a[pos] = num ;
    }
} ttt ;
int main () {
    int T , m ;
//  freopen ( "a.in" , "r" , stdin ) ;
  scanf ( "%d" , &T ) ;
    while ( T -- ) {
		scanf ( "%d%d" , &n , &m ) ;
        for ( int i = 1 ; i <= n ; i ++ )
            scanf ( "%d" , &a[i] ) ;
        ttt.init () ;
        while ( m -- ) {
            char op[11] ;
            int x , y , z ;
            scanf ( "%s" , op ) ;
            if ( op[0] == 'Q' ) {
                scanf ( "%d%d%d" , &x , &y , &z ) ;
                printf ( "%d\n" , ttt.ask ( x , y , z ) ) ;
            } else {
                scanf ( "%d%d" , &x , &y ) ;
                ttt.modify ( x , y ) ;
            }
        }
    }
    return 0 ;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值