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\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 , 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\n" , 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\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 , 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\n" , ttt.ask ( x , y , z ) ) ;
} else {
scanf ( "%d%d" , &x , &y ) ;
ttt.modify ( x , y ) ;
}
}
}
return 0 ;
}

bzoj 1901: Zju2112 Dynamic Rankings(树套树)的更多相关文章

  1. BZOJ 1901: Zju2112 Dynamic Rankings( BIT 套 BST )

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

  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 -- 主席树,树状数组,哈希

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

  7. BZOJ 1901 Zju2112 Dynamic Rankings

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

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

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

  9. BZOJ 1901 Zju2112 Dynamic Rankings 树状数组套线段树

    题意概述:带修改求区间第k大. 分析: 我们知道不带修改的时候直接上主席树就可以了对吧?两个版本号里面的节点一起走在线段树上二分,复杂度是O((N+M)logN). 然而这里可以修改,主席树显然是凉了 ...

随机推荐

  1. vs 2010 引用DLL 遇到问题

    1.新建项目→添加引用,提示:未能添加对dll的引用,请确保此文件可访问并且是一个有效的程序集或COM组件 解决方案:首先把DLL放system32中,然后,regsvr32 绝对路径注册一下: 如果 ...

  2. Laravel 5.1 ACL权限控制 三 之权限准备及实现权限管理

    请自动参照到上上篇文章 1.创建控制器 php artisan make:model Permission php artisan make:model Role 2.创建表 php artisan ...

  3. PHPExcel 生成excel统计表格

    db.php为数据库操作类, $config为数据库配置,PHPExcel版本为PHPExcel_1.8.0,  php代码: $dir = dirname(__FILE__); require $d ...

  4. 我的Python成长之路---第六天---Python基础(18)---2016年2月20日(晴)

    os模块 提供对操作系统进行调用的接口 >>> import os >>> os.getcwd() # 获取当前工作目录,类似linux的pwd命令 '/data/ ...

  5. 405 HTTP method GET is not supported by this URL

    孙鑫java web开发详解P285里面提交Get网站弹出提示405 HTTP method GET is not supported by this URL 原因父类doGet()方法未覆盖. 应写 ...

  6. Ubuntu基本设置

    (1)  为了启用 root 帐号 (也就是 设置一个口令) 使用: sudo passwd root 1.设置IP, 终端输入 sudo gedit /etc/network/interfaces ...

  7. The Priest Mathematician

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31329#problem/F f[0] = 1 , f[ i ] = f[ i - 1 ] ...

  8. VBS脚本病毒特点及如何防范3(转)

    5.Vbs病毒生产机的原理介绍 所谓病毒生产机就是指可以直接根据用户的选择产生病毒源代码的软件.在很多人看来这或许不可思议,其实对脚本病毒而言它的实现非常简单. 脚本语言是解释执行的.不需要编译,程序 ...

  9. AFNetworking GET和POST请求

    GET请求 代码展示: 在storyBoard中每个请求关联一个Button #pragma mark - get请求 - (IBAction)getRequest:(id)sender { // 参 ...

  10. asp.net mvc 下载文件 txt doc xsl 等等

      不废话,直接上代码,就是这么简单 public FileStreamResult StreamFileFromDisk() { // string path = AppDomain.Current ...