• BZOJ 1901: Zju2112 Dynamic Rankings( BIT 套 BST )


    BIT 套 splay

     其实也是不难...每个 BIT 的结点保存一颗 splay , 询问就二分答案然后判断rank...

    ---------------------------------------------------------------

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<iostream>
     
    #define rep( i , n ) for( int i = 0 ; i < n ; ++i )
    #define clr( x , c ) memset( x , c , sizeof( x ) )
    #define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
    #define lowbit( x ) ( ( x ) & ( -x ) )
     
    using namespace std;
     
    const int maxn = 10000 + 5;
    const int maxnode = 5e6;
    const int inf = 2e9;
     
    int n , mn , mx;
    int seq[ maxn ];
     
    struct Node* null;
     
    queue< Node* > Q;
     
    struct Node {
    Node *ch[ 2 ] , *p;
    int v , s;
    Node( int _ = inf ) : v( _ ) , s( 1 ) {
    ch[ 0 ] = ch[ 1 ] = p = null;
    }
    inline bool d() {
    return this == p -> ch[ 1 ];
    }
    inline void setc( Node* c , int d ) {
    ch[ d ] = c;
    c -> p = this;
    }
    inline void upd() {
    s = ch[ 0 ] -> s + ch[ 1 ] -> s + 1;
    }
    void* operator new( size_t ) {
    Node* t = Q.front(); Q.pop();
    return t;
    }
    };
     
    Node pool[ maxnode ];
     
    struct SPLAY {
    Node* root;
    void rot( Node* t ) {
    Node* p = t -> p;
    int d = t -> d();
    p -> p -> setc( t , p -> d() );
    p -> setc( t -> ch[ d ^ 1 ] , d );
    t -> setc( p , d ^ 1 );
    p -> upd();
    if( p == root )
       root = t;
    }
    void splay( Node* t , Node* f = null ) {
    for( Node* p = t -> p ; p != f ; p = t -> p ) {
    if( p -> p != f )
       p -> d() != t -> d() ? rot( t ) : rot( p );
    rot( t );
    }
    t -> upd();
    }
    Node* select( int k ) {
    for( Node* t = root ; ; ) {
    int s = t -> ch[ 0 ] -> s;
    if( k == s ) return t;
    if( k > s )
       k -= s + 1 , t = t -> ch[ 1 ];
    else 
       t = t -> ch[ 0 ];
    }
    }
    int rank( int v ) {
    int ans = 0;
    for( Node* t = root ; t != null ; )
    if( t -> v < v )
       ans += t -> ch[ 0 ] -> s + 1 , t = t -> ch[ 1 ];
    else
       t = t -> ch[ 0 ];
    return ans;
    }
    void insert( int v ) {
    int k = rank( v );
    Node *L = select( k - 1 ) , *R = select( k );
    splay( L ) , splay( R , L );
    R -> setc( new Node( v ) , 0 );
    R -> upd();
    root -> upd();
    }
    void del( int v ) {
    int k = rank( v );
    Node *L = select( k - 1 ) , *R = select( k + 1 );
    splay( L );
    splay( R , L );
    Q.push( R -> ch[ 0 ] );
    R -> setc( null , 0 );
    R -> upd();
    L -> upd();
    }
    };
     
    SPLAY h[ maxn ];
     
    void init() {
    rep( i , maxnode ) Q.push( pool + i );
    null = new Node();
    null -> s = 0;
    Rep( i , n ) {
    h[ i ].root = new Node();
    h[ i ].root -> setc( new Node( -inf ) , 0 );
    h[ i ].root -> upd();
    }
    }
     
    inline void del( int x , int v ) {
    for( ; x <= n ; x += lowbit( x ) )
    h[ x ].del( v );
    }
     
    inline void insert( int x , int v ) {
    for( ; x <= n ; x += lowbit( x ) )
       h[ x ].insert( v );
    }
     
    inline int rank( int l , int r , int v ) {
    int ans = 0;
    for( l-- ; l ; l -= lowbit( l ) )
      ans -= h[ l ].rank( v ) - 1;
    for( ; r ; r -= lowbit( r ) )
      ans += h[ r ].rank( v ) - 1;
    return ans + 1;
    }
     
    int query( int l , int r , int k ) {
    int L = mn , R = mx , ans;
    while( L <= R ) {
    int m = ( L + R ) >> 1;
    if( rank( l , r , m ) > k ) 
       R = m - 1;
    else 
       L = ( ans = m ) + 1;
    }
    return ans;
    }
     
    void modify( int pos , int v ) {
    del( pos , seq[ pos ] );
    insert( pos , seq[ pos ] = v );
    }
     
    int main() {
    freopen( "test.in" , "r" , stdin );
    freopen( "test.out" , "w" , stdout );
    int q;
    cin >> n >> q;
    init();
    Rep( i , n ) {
       scanf( "%d" , seq + i );
       insert( i , seq[ i ] );
    }
    mn = mx = seq[ 1 ];
    for( int i = 2 ; i <= n ; ++i ) {
    mx = max( seq[ i ] , mx );
    mn = min( seq[ i ] , mn );
    }
    char c;
    while( q-- ) {
    scanf( " %c" , &c );
    if( c == 'Q' ) {
    int l , r , k;
    scanf( "%d%d%d" , &l , &r , &k );
    int t = query( l , r , k ) , p = *min_element( seq + l , seq + r + 1 );
    for( int i = l ; i <= r ; ++i )
       if( seq[ i ] <= t && seq[ i ] > p )
           p = seq[ i ];
    printf( "%d " , p );
    } else {
    int pos , v;
    scanf( "%d%d" , &pos , &v );
    mn = min( v , mn );
    mx = max( v , mx );
    modify( pos , v );
    }
    }
    return 0;
    }

    --------------------------------------------------------------- 

    1901: Zju2112 Dynamic Rankings

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 5363  Solved: 2243
    [Submit][Status][Discuss]

    Description

    给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。

    Input

    对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

    Output

    Sample Input

    5 3
    3 2 1 4 7
    Q 1 4 3
    C 2 6
    Q 2 5 3

    Sample Output

    3
    6

    HINT

    20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

    Source

  • 相关阅读:
    [BZOJ]1018 堵塞的交通(SHOI2008)
    [BZOJ]1069 最大土地面积(SCOI2007)
    HDU5739:Fantasia——题解
    洛谷6186:[NOI Online 提高组]冒泡排序——题解
    洛谷4631 & UOJ415 & LOJ2586:[APIO2018] Circle selection 选圆圈——题解
    洛谷2014:[CTSC1997]选课——题解
    洛谷2758:编辑距离——题解
    洛谷4148 & BZOJ4066:简单题——题解
    洛谷4357 & BZOJ4520:[CQOI2016]K远点对——题解
    洛谷4320:道路相遇——题解
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4625552.html
Copyright © 2020-2023  润新知