zoukankan      html  css  js  c++  java
  • bzoj 1901: Zju2112 Dynamic Rankings(树套树)

    1901: Zju2112 Dynamic Rankings

    经典的带改动求区间第k小值问题

    树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过不了。

    思路非常easy,用线段树维护区间,用splay维护区间内的权值,然后询问的时候,二分答案key,然后在区间内找小于key的数有多少个。

    贴上模板:

    #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]
    using namespace std ;
     
    const int maxn = 100001 ;
    const int N = maxn*18 ;
    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[N] , 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
    " , rt , size[rt] ) ;
            printf ( "ls = %d , rs = %d , fa = %d , val = %d
    " , 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 , int l , int r , int rt ) {
            if ( op == 0 ) {
                add ( root[rt] , v ) ;
            }
            else del ( root[rt] , v ) ;
            if ( l == r ) return ;
            int m = l + r >> 1 ;
            if ( pos <= m ) update ( pos , v , op , lson ) ;
            else update ( pos , v , op , rson ) ;
        }
        int count ( int a , int b , int v , int l , int r , int rt ) {
            if ( a <= l && r <= b ) {
                int k = count_smaller ( root[rt] , v ) - 1 ;
                return k ;
            }
            int m = l + r >> 1 , ret = 0 ;
            if ( a <= m ) ret = count ( a , b , v , lson ) ;
            if ( m < b ) ret += count ( a , b , v , rson ) ;
            return ret ;
        }
        void init () {
            tot = 0 ;
            top = 0 ;
            build ( 1 , n , 1 ) ;
            for ( int i = 1 ; i <= n ; i ++ ) {
        //      printf ( "a[%d] = %d
    " , i , a[i] ) ;
                update ( i , a[i] , 0 , 1 , n , 1 ) ;
            }
        }
        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 , 1 , n , 1 ) ;
    //          printf ( "m = %d , cnt = %d
    " , m , cnt ) ;
                if ( cnt <= k - 1 ) l = m + 1 ;
                else r = m - 1 ;
    //          printf ( "l = %d , r = %d
    " , l , r ) ;
            }
            return r ;
        }
        void modify ( int pos , int num ) {
            update ( pos , a[pos] , 1 , 1 , n , 1 ) ;
            update ( pos , num , 0 , 1 , n , 1 ) ;
            a[pos] = num ;
        }
    } ttt ;
    int main () {
        int T , m ;
    //  freopen ( "a.in" , "r" , stdin ) ;
    //  scanf ( "%d" , &T ) ;
        while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
            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
    " , ttt.ask ( x , y , z ) ) ;
                } else {
                    scanf ( "%d%d" , &x , &y ) ;
                    ttt.modify ( x , y ) ;
                }
            }
        }
        return 0 ;
    }


  • 相关阅读:
    发张照片纪念下
    以用户为中心的SNS站点数据库设计及实现
    IT点评:腾讯帝国没落的开始从崇敬到平淡,改变从自己开始
    并发下常见的加锁及锁的PHP具体实现
    Ubuntu,Your Linux
    Python初尝试
    C++ Primer Plus读书笔记02
    C++ Primer Plus读书笔记03
    Effective C++读书笔记02
    由扔骰子看平均概率生成
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/4260126.html
Copyright © 2011-2022 走看看