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\n" , 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 1901: Zju2112 Dynamic Rankings( BIT 套 BST )的更多相关文章

  1. bzoj 1901: Zju2112 Dynamic Rankings(树套树)

    1901: Zju2112 Dynamic Rankings 经典的带改动求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过 ...

  2. Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6471  Solved: 2697[Su ...

  3. BZOJ 1901: Zju2112 Dynamic Rankings( 树状数组套主席树 )

    裸的带修改主席树.. 之前用BIT套Splay( http://www.cnblogs.com/JSZX11556/p/4625552.html )A过..但是还是线段树好写...而且快(常数比平衡树 ...

  4. BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7143  Solved: 2968[Su ...

  5. Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6321  Solved: 2628[Su ...

  6. BZOJ 1901 Zju2112 Dynamic Rankings

    树阵主席设置树.维护间隔动态K大. .. ZOJ到空间太小,太大,仅仅能到BZOJ上交 1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memor ...

  7. bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...

  8. BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树

    之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池 ...

  9. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

随机推荐

  1. c#与.NET的区别

    C#与.NET的关系 C# 可以通过.NET平台来编写 部署 运行.NET应用程序VB.NET.......NET语言 C#是专门为.NET平台而生的(面向对象) .NET平台的重要组成:1.FCL- ...

  2. Angular JS 学习笔记(二)

    1. AngularJS 是一个 JavaScript 框架.它可通过 <script> 标签添加到 HTML 页面.AngularJS 通过 指令 扩展了 HTML,且通过 表达式 绑定 ...

  3. SSIS 阻塞,半阻塞和全阻塞 (Non-blocking, semi-blocking and Fully-blocking) transformations清单

    三种Blocking类型,这里跟数据流的Buff关系很大:■■ non-blocking transformations,每一行直接转换输出,没有等待.■■ partial-blocking tran ...

  4. Oracle行转列实例

    行转列之前的数据: select * from tbname; 行转列之后的数据: select pud, listagg(ud, ',') within group(order by null) a ...

  5. c++实现二分查找

    简要描述: 二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除 困难. 条件:查找的数组必须要为有序数组. 二分查找的过程剩简要描述如下图: 二种实 ...

  6. APACHE的伪静态设置

    1.配置httpd.conf #LoadModule rewrite_module modules/mod_rewrite.so 开启 LoadModule rewrite_module module ...

  7. Qt 错误: 无法运行 release 下的可执行文件

        学习Qt有一点时间了,但之前都是在debug版本下进行编译运行,偶然切换到release版本下,却出现了如下错误: 错误提示:   This application failed to sta ...

  8. Mac编程(QT有许多专门的资料)

    Mac OS X 上在应用运行时,在Dock上的图标右键会有额外的菜单部分.参考iTunes运行时右键的菜单.使用Qt在Mac下的一个set_menu(QMenu *)函数实现,文档里有写 http: ...

  9. 函数重载不仅仅是看其参数,还要看是否有const修饰

    比如QString有两个函数,可以堂而皇之的存在,原因就在于有了const修饰以后,编译器不把两个函数当作同一个函数名了: QChar * data() const QChar * data() co ...

  10. iOS SDK:预览和打开文档

    iOS中的沙盒可以让平台更加的安全,这也是沙盒给用户带来的最主要好处.不过由于沙盒的严格限制,导致程序之间共享数据比较麻烦.一般在程序间共享文档可以通过UIDocumentInteractionCon ...