The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They have developed a more powerful system such that for N numbers a[1], a[2], ..., a[N], you can ask it like: what is the k-th smallest number of a[i], a[i+1], ..., a[j]? (For some i<=j, 0<k<=j+1-i that you have given to it). More powerful, you can even change the value of some a[i], and continue to query, all the same.

Your task is to write a program for this computer, which

- Reads N numbers from the input (1 <= N <= 50,000)

- Processes M instructions of the input (1 <= M <= 10,000). These instructions include querying the k-th smallest number of a[i], a[i+1], ..., a[j] and change some a[i] to t.

Input

The first line of the input is a single number X (0 < X <= 4), the number of the test cases of the input. Then X blocks each represent a single test case.

The first line of each block contains two integers N and M, representing N numbers and M instruction. It is followed by N lines. The (i+1)-th line represents the number a[i]. Then M lines that is in the following format

Q i j k or
C i t

It represents to query the k-th number of a[i], a[i+1], ..., a[j] and change some a[i] to t, respectively. It is guaranteed that at any time of the operation. Any number a[i] is a non-negative integer that is less than 1,000,000,000.

There're NO breakline between two continuous test cases.

<b< dd="">

Output

For each querying operation, output one integer to represent the result. (i.e. the k-th smallest number of a[i], a[i+1],..., a[j])

There're NO breakline between two continuous test cases.

Sample Input

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

Sample Output

3
6
3
6

第一次写树套树,而且应该是最基础的树套树,手抄大佬函数,自己整理成结构体。

没看别人题解的时候再高数课上YY,以为是对于线段树的每个节点套一个平衡树,这样的话想了一下,开的空间大概是n*lgn*n,基本上是炸了的。

但是好像没有必要每个节点建立一个Treap,每个Treap给n个节点。因为过于浪费。

大佬们好像是只建立一个大Treap,但是有n个root,然后把空间分配到小Treap里面。

但是这样空间开n*lgn*lgn,好像1000000的空间还是不够处理极限情况啊。。。不知道这么回事。

copy from qscqesze 顾学姐?结合前两天写的线段树和Treap,我们两个的风格还是比较像的,所以我理解代码起来也比较快。ORZ。。。对于空间的问题,多做几个题再回头分析。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<ctime>
using namespace std;
#define maxn 1000001
int tmp=;
struct Treap
{
int root[maxn],sz,s[maxn],ch[maxn][],v[maxn],w[maxn],rnd[maxn];//s是size,w是cnt
//rnd小根堆
void init()
{
memset(root,,sizeof(root));
sz=;
}
void Update(int now)
{
s[now]=s[ch[now][]]+s[ch[now][]]+w[now];
}
void rotate(int &now,int p)
{
int t=ch[now][p];
ch[now][p]=ch[t][-p],ch[t][-p]=now,s[t]=s[now];
Update(now);now=t;//好像明白了为什么要替代:k得到儿子信息
}
void Insert(int &now,int num)
{
if(!now){
now=++sz;s[now]=w[now]=;ch[now][]=ch[now][]=;rnd[now]=rand();
v[now]=num;return;
}
s[now]++;
if(v[now]==num)w[now]++;
else{
int t=num>v[now];
Insert(ch[now][t],num);
if(rnd[ch[now][t]]<rnd[now])
rotate(now,t);
}
}
void Del(int &now,int num)//code better than mine before
{
if(v[now]==num){
if(w[now]>){
w[now]--;
s[now]--;
return;
}
if(ch[now][]*ch[now][]==)
now=ch[now][]+ch[now][];
else rotate(now,rnd[ch[now][]]>rnd[ch[now][]]),Del(now,num);
}
else {
Del(ch[now][num>v[now]],num);
s[now]--;
}
}
void Find(int now,int num)
{
if(!now) return;
if(v[now]<=num){
tmp+=s[ch[now][]]+w[now];
Find(ch[now][],num);
}
else Find(ch[now][],num);
}
}Tr;
/////////////////////线段树
void Seg_insert(int now,int l,int r,int x,int num)
{
Tr.Insert(Tr.root[now],num);
if(l==r)return;
int mid=(l+r)>>;
if(x<=mid)Seg_insert(now<<,l,mid,x,num);
else Seg_insert(now<<|,mid+,r,x,num);
} void Seg_change(int now,int l,int r,int x,int Now,int Pre)
{
Tr.Del(Tr.root[now],Pre);
Tr.Insert(Tr.root[now],Now);
if(l==r)return;
int mid=(l+r)>>;
if(x<=mid)Seg_change(now<<,l,mid,x,Now,Pre);
else Seg_change(now<<|,mid+,r,x,Now,Pre);
}
void Seg_query(int now,int l,int r,int L,int R,int num)
{
if(l==L&&r==R)
{
Tr.Find(Tr.root[now],num);
return;
}
int mid = (l+r)>>;
if(mid>=R)
Seg_query(now<<,l,mid,L,R,num);
else if(mid<L)
Seg_query(now<<|,mid+,r,L,R,num);
else{
Seg_query(now<<,l,mid,L,mid,num);
Seg_query(now<<|,mid+,r,mid+,R,num);
}
}
///////////////////////////
int a[maxn];
int main()
{
int T;scanf("%d",&T);
while(T--)
{
Tr.init();
int n,m;scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
Seg_insert(,,n,i,a[i]);
}
char op[];
for(int i=;i<=m;i++){
scanf("%s",op);
if(op[]=='C'){
int x,y;scanf("%d%d",&x,&y);
Seg_change(,,n,x,y,a[x]);
a[x]=y;
}
else{
int x,y,z;scanf("%d%d%d",&x,&y,&z);
int l = ,r = 1e9;
while(l<=r){
int mid = (l+r)>>;
tmp=; Seg_query(,,n,x,y,mid);
if(tmp>=z)r=mid-;
else l=mid+;
}
printf("%d\n",l);
}
}
}
return ;
}

(2700ms左右);

这题还有主席树(200ms左右)

代码见:http://www.cnblogs.com/hua-dong/p/7931778.html

ZOJ2112 Dynamic Rankings (线段树套平衡树)(主席树)的更多相关文章

  1. Dynamic Rankings—带单点修改的主席树

    这道题应该是很不错的板子了\(\mathcal{\color{cyan}{Link}}\) \(\mathcal{\color{red}{Description}}\) 给定一个序列,有两种操作.一是 ...

  2. BZOJ.1901.Dynamic Rankings(线段树套平衡树 Splay)

    题目链接or Here 题意:n个数,有两个操作:1.修改某个数为v:2.询问一段区间第k小的数 如果没有修改,则可以用线段树,每个节点P[a,b]存储大小为b-a+1的数组,代表其中的数 同时,这个 ...

  3. ZOJ - 2112 Dynamic Rankings(BIT套主席树)

    纠结了好久的一道题,以前是用线段树套平衡树二分做的,感觉时间复杂度和分块差不多了... 终于用BIT套函数式线段树了过了,120ms就是快,此题主要是卡内存. 假设离散后有ns个不同的值,递归层数是l ...

  4. 树套树Day1线段树套平衡树bzoj3196

    您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...

  5. 浅谈树套树(线段树套平衡树)&学习笔记

    0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...

  6. [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)

    题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...

  7. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2271  Solved: 935[Submit][Stat ...

  8. CF 19D - Points 线段树套平衡树

    题目在这: 给出三种操作: 1.增加点(x,y) 2.删除点(x,y) 3.询问在点(x,y)右上方的点,如果有相同,输出最左边的,如果还有相同,输出最低的那个点 分析: 线段树套平衡树. 我们先离散 ...

  9. BZOJ3196二逼平衡树——线段树套平衡树(treap)

    此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...

  10. P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)

    P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...

随机推荐

  1. loadrunder之脚本篇——加密解密

    密码加密 可以给密码加密,意在把结果字符串作为脚本的参数或者参数值.例如,完整可能有一个用户密码填写的表单,你想测试网站针对不同密码的反应,但是你又想保护密码的安全.Password Encoder允 ...

  2. C++中引用编译过的C代码为什么要用“extern c”

    函数经过编译系统的翻译成汇编,函数名对应着汇编标号.  因为C编译函数名与得到的汇编代号基本一样,如:fun()=>_fun, main=>_main  但是C++中函数名与得到的汇编代号 ...

  3. iOS 结构简单清晰的 设置页面

    这个是也是看了人家的代码,觉得甚是简单清晰,也是比较容易扩展.拿来学习一下 效果展示: 重点有以下2处: 1 .建立groupModel 列清组元素:当前组list 集合, 是否有header 或者 ...

  4. Scalability, Availability & Stability Patterns

    https://blog.csdn.net/ajian005/article/details/6191814   一 自我有要求的读者应该提出问题:(研习:掌握层次:)能力级别:不会(了解)——领会( ...

  5. grep的若干用法

    查找包含server或者client的行 egrep 'server|client' file-name /usr/xpg4/bin/grep -E 'server|client' file-name ...

  6. Linux串口编程(中断方式和select方式)

    Linux下的串口编程,在嵌入式开发中占据着重要的地位,因为很多的嵌入式设备都是通过串口交换数据的.在没有操作系统的我们可以使用UART的中断来出来数据的接受和发送,而在Linux操作系统下,我们也可 ...

  7. 网络:W5500 UDP数据包格式注意事项

     1. 主题 使用W5500测试UDP功能,发现收到的数据包和wireshark抓包的数据不同. 原来W5500接收寄存器的数据包并不是网络上的数据流,而是经过内部处理后展现出来的. 对于这个问题目前 ...

  8. c++ 关键字extern(声明)和定义的区别

    extern  : extern  int  i; // declares but does not define i int i;         //declares and defines i ...

  9. 深入理解JVM1

    1 Java技术与Java虚拟机 说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成: Java编程语言.Java类文件格式.Java虚拟机和Java应用程 ...

  10. Go 语言基础知识

    0. Go语言书单 1. 文本注释 // 单行注释 /* */ 多行注释 2. 变量赋值 = 变量赋值 := 声明变量并赋值 3. 变量定义 var name string var age int v ...