ZOJ2112 Dynamic Rankings (线段树套平衡树)(主席树)
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 (线段树套平衡树)(主席树)的更多相关文章
- Dynamic Rankings—带单点修改的主席树
这道题应该是很不错的板子了\(\mathcal{\color{cyan}{Link}}\) \(\mathcal{\color{red}{Description}}\) 给定一个序列,有两种操作.一是 ...
- BZOJ.1901.Dynamic Rankings(线段树套平衡树 Splay)
题目链接or Here 题意:n个数,有两个操作:1.修改某个数为v:2.询问一段区间第k小的数 如果没有修改,则可以用线段树,每个节点P[a,b]存储大小为b-a+1的数组,代表其中的数 同时,这个 ...
- ZOJ - 2112 Dynamic Rankings(BIT套主席树)
纠结了好久的一道题,以前是用线段树套平衡树二分做的,感觉时间复杂度和分块差不多了... 终于用BIT套函数式线段树了过了,120ms就是快,此题主要是卡内存. 假设离散后有ns个不同的值,递归层数是l ...
- 树套树Day1线段树套平衡树bzoj3196
您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...
- 浅谈树套树(线段树套平衡树)&学习笔记
0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2271 Solved: 935[Submit][Stat ...
- CF 19D - Points 线段树套平衡树
题目在这: 给出三种操作: 1.增加点(x,y) 2.删除点(x,y) 3.询问在点(x,y)右上方的点,如果有相同,输出最左边的,如果还有相同,输出最低的那个点 分析: 线段树套平衡树. 我们先离散 ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)
P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
随机推荐
- 谷歌机器学习速成课程---3降低损失 (Reducing Loss):梯度下降法
迭代方法图(图 1)包含一个标题为“计算参数更新”的华而不实的绿框.现在,我们将用更实质的方法代替这种华而不实的算法. 假设我们有时间和计算资源来计算 w1 的所有可能值的损失.对于我们一直在研究的回 ...
- paramiko 模块安装和使用
一.Centos安装Paramiko 1.安装组件 yum install openssl openssl-devel python-dev pycrypto -y yum install zlib- ...
- Windows彻底卸载VMWare虚拟机
彻底卸载VMWare虚拟机 1.停止VMware相关服务 在服务中将VMware开头的所有服务停止 2.打开VMware安装向导 进入卸载页面 在卸载页面中选中VMware右键点击,进入更改后,页面为 ...
- Python自然语言处理 - 系列四
一 如何使用形式化语法来描述无限的句子集合的结构? --上下位无关文法 1.1 一个例子: grammar1 = nltk.parse_cfg(""&q ...
- Android L 64位兼容32 应用程序的认识
http://blog.csdn.net/louyong0571/article/details/44223481 关于Android L 64位系统兼容32位应用的实现的简单分析. Android ...
- 【鸟哥的Linux私房菜】笔记
操作系统核心的功能! 驱动程序与操作系统的关系 2. [计算机组成之组件] 3.CPU实际要处理的数据完全来自于主存储器,这是一个很重要的概念! 4.CPU是整个计算机系统最重要的部分,那么目前世界上 ...
- nodejs爬虫selenium
6.元素操作 查找元素 使用操作如何找到页面元素Webdriver的findElement方法可以用来找到页面的某个元素,最常用的方法是用id和name查找.下面介绍几种比较常用的方法. By ID假 ...
- 对vector,list的操作函数
向量只能接受同一类型的数据:list可以接受不同的数据. 1.添加元素 vector:> b=c(1,2,3) > b=c(b,"four") #直接在后面添加添加 & ...
- Whitewidow:SQL 漏洞自动扫描工具
Whitewidow 是一个开源的 SQL 漏洞自动扫描器,可用通过文件列表运行,或者从 Google 爬取并发现有潜在漏洞的网站. 这个工具支持自动格式化文件.随机用户代理.IP 地址.服务器信息. ...
- java深入探究12-框架整合
1.Spring与Hibernate整合 需要配置的就是hibernate和bean.xml 1)关键点:sessionFactory创建交给SpringIOC:session的事务处理交给Sprin ...