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. Longest Substring Without Repeating Characters - 哈希与双指针

    题意很简单,就是寻找一个字符串中连续的最长包含不同字母的子串. 其实用最朴素的方法,从当前字符开始寻找,找到以当前字符开头的最长子串.这个方法猛一看是个n方的算法,但是要注意到由于字符数目的限制,其实 ...

  2. CentOS环境下R语言的安装和配置

    最近在看数据统计和分析,想到了R语言,于是就着手在自己的CentOS环境下进行安装和配置.步骤如下: 1.前往R官网下载安装包. 2.解压压缩包:tar xvzf R-3.2.2.tar.gz 3.进 ...

  3. 【c语言】求最大值

    一.我个人觉得求最大值比较简单的一种方法(当然同时求最大值和最小值时稍微改改也能行) #include <stdio.h> int main(void) { int f, i, max; ...

  4. 深入浅出—JAVA(10)

    10.数字与静态 静态变量是共享的.同一类所有的实例共享一份静态变量. 实例变量:每个实例一个.静态变量:每个类一个. 数字的格式化 唯一必填的项目是类型 package xiao;class Sta ...

  5. 汇总:Linux下10款即时通讯客户端,skype

    aMSN 是一款功能强大的MSN(WLM)的客户端,支持皮肤.插件.系统托盘图标.摄像头.多帐号登录.离线信息等. Pidgin 不用说了,是GNOME下的IM客户端,支持AIM, Google Ta ...

  6. 设计模式(一)工厂模式Factory(创建型)

    设计模式一 工厂模式Factory 在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的.可是在一些情况下, new操作符直接生成对象会带来一些问题. ...

  7. Linux 静态库与共享库的使用

    申明: 正如题如示,本篇讲的是Linux下是静态库与共享库,而Window下的动态链接库详细情况可见这篇文章:windows动态链接库 DLL 浅析.虽然原理,思想差不多,但是细节却各有不同. 一.静 ...

  8. 关于方法的ref

    没有ref的方法时: using System; using System.Collections.Generic; using System.Linq; using System.Text; usi ...

  9. opencv kmeans 图像分割

    利用kmeans算法,将彩色图像的像素点作为样本,rgb值作为样本的属性, 对图像所有的像素点进行分类,从而实现对图像中目标的分割. c++代码(openCV 2.4.11) Scalar color ...

  10. [GDUT 决赛]--GCD,LCM——我是好人(数论)

    Description 众所周知,我是好人!所以不会出太难的题,题意很简单 给你两个数n和m,问你有多少对正整数对最大公约数是n,最小公倍数是m最后友情提供解题代码(我真是太好人了) void sol ...