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(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
随机推荐
- nfs共享存储
1.下载软件包 yum install nfs-utils nfs-utils-lib -y 2.编辑/etc/exports文件: 1.创建目录:mkdir -p /home/glance2.编辑e ...
- active scaffold
模板文件路径:/.rvm/gems/ruby-2.2.3/gems/active_scaffold-3.5.3/app/views/active_scaffold_overrides
- predis操作大全
predis是php连接redis的操作库,由于它完全使用php编写,大量使用命名空间以及闭包等功能,只支持php5.3以上版本,故实测性能一般,每秒25000次读写,相信改换c语言编写的php扩展后 ...
- Loadrunder脚本篇——web_custom_request做接口测试
一.POST + JSON格式参数 例: web_custom_request("create", "URL=http://xxx.xxx.x.xx:1600/ditui ...
- spring data jpa是什么?
JPA是一个Java编程语言接口规范,Hibernate ORM是JPA规范的一个实现. Spring Data JPA能干什么 在开始之前,先举个简单的例子. 一张表user有三个字段,id.n ...
- lambda可调用对象
//find_if谓词使用 bool isShorter(const string &s1, const string &sz){ return s1.size() < sz.s ...
- HTML5(。。。。不完整)
<!DOCTYPE html> 不区分大小写 <header>.<nav>.<article>.<section>.<sidebar ...
- Struts2笔记04——Hello World Example(转)
原文地址:https://www.tutorialspoint.com/struts_2/ [注释]项目结构,次序估计有误 通过学习Struts2的架构,我们可以知道,在Struts2 web应用中, ...
- Qt打包过大
经常看到网上有些论调说 Qt 程序无比庞大,甚至拿 .NET 程序来比,说 Qt 程序打包以后跟 .NET 安装包差不多大.由此影响了很多人对 Qt 的选择.我觉得有必要对此做一些澄清—— 显然这个说 ...
- ubuntu关闭631(cups)端口
在ubuntu17.04环境下使用nmap扫描自己机器,发现631端口处于开启状态,将其输入到浏览器,可以看出是网络打印机的服务: 这个端口开着总是那么的刺眼,(5.12全球爆发的勒索病毒让人不寒而栗 ...