zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap
Dynamic Rankings
Time Limit: 20 Sec
Memory Limit: 256 MB
题目连接
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112
Description
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.
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
HINT
题意
动态第k大
1. Q x y k,查询区间[x,y]第k大的数是啥
2. C x y,把第x个数变成y
题解:
树套树
在每一个区间里面,我们都套入一个Treap/Splay就好了
1操作很简单,暴力进行二分就好了,我们在[L,R]区间所在的Treap里面查询Rank
2操作,在所有这个数所在的区间,我们都删除原来的,再加入新的就好了
代码:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<ctime>
using namespace std; #define maxn 1000001
int tmp = ;
////////////////treap
struct Treap
{
int root[maxn],sz,s[maxn],ls[maxn],rs[maxn],v[maxn],w[maxn],rnd[maxn];
void init()
{
memset(root,,sizeof(root));
sz=;
}
void Updata(int k)
{
s[k]=s[ls[k]]+s[rs[k]]+w[k];
}
void Rturn(int &k)
{
int t;
t=ls[k],ls[k]=rs[t],rs[t]=k,s[t]=s[k];
Updata(k);k=t;
}
void Lturn(int &k)
{
int t;
t=rs[k],rs[k]=ls[t],ls[t]=k,s[t]=s[k];
Updata(k);k=t;
}
void Insert(int &k,int num)
{
if(!k)
{
k=++sz;s[k]=w[k]=;ls[k]=rs[k]=;rnd[k]=rand();
v[k]=num;return;
}
s[k]++;
if(v[k]==num)w[k]++;
else if(num<v[k])
{
Insert(ls[k],num);
if(rnd[ls[k]]<rnd[k])
Rturn(k);
}
else
{
Insert(rs[k],num);
if(rnd[rs[k]]<rnd[k])
Lturn(k);
}
}
void Del(int &k,int num)
{
if(v[k]==num)
{
if(w[k]>){
w[k]--;
s[k]--;
return;
}
if(ls[k]*rs[k]==)
k=ls[k]+rs[k];
else if(rnd[ls[k]]<rnd[rs[k]])
Rturn(k),Del(k,num);
else
Lturn(k),Del(k,num);
}
else if(num<v[k]){
Del(ls[k],num);
s[k]--;
}
else{
Del(rs[k],num);
s[k]--;
}
}
void Find(int k,int num)
{
if(!k)return;
if(v[k]<=num){
tmp+=s[ls[k]]+w[k];
Find(rs[k],num);
}
else Find(ls[k],num);
}
}Tr; ///////////////////// /////////////////////线段树 void Seg_insert(int k,int l,int r,int x,int num)
{
Tr.Insert(Tr.root[k],num);
if(l==r)return;
int mid=(l+r)/;
if(x<=mid)Seg_insert(k*,l,mid,x,num);
else Seg_insert(k*+,mid+,r,x,num);
} void Seg_change(int k,int l,int r,int x,int Now,int Pre)
{
Tr.Del(Tr.root[k],Pre);
Tr.Insert(Tr.root[k],Now);
if(l==r)return;
int mid=(l+r)/;
if(x<=mid)Seg_change(k*,l,mid,x,Now,Pre);
else Seg_change(k*+,mid+,r,x,Now,Pre);
}
void Seg_query(int k,int l,int r,int L,int R,int num)
{
if(l==L&&r==R)
{
Tr.Find(Tr.root[k],num);
return;
}
int mid = (l+r)/;
if(mid>=R)
Seg_query(k*,l,mid,L,R,num);
else if(mid<L)
Seg_query(k*+,mid+,r,L,R,num);
else{
Seg_query(k*,l,mid,L,mid,num);
Seg_query(k*+,mid+,r,mid+,R,num);
}
}
///////////////////////////
int a[maxn];
int main()
{
srand(time(NULL));
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);
}
}
}
}
zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap的更多相关文章
- ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)
题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...
- 整体二分&cdq分治 ZOJ 2112 Dynamic Rankings
题目:单点更新查询区间第k大 按照主席树的思想,要主席树套树状数组.即按照每个节点建立主席树,然后利用树状数组的方法来更新维护前缀和.然而,这样的做法在实际中并不能AC,原因即卡空间. 因此我们采用一 ...
- 主席树[可持久化线段树](hdu 2665 Kth number、SP 10628 Count on a tree、ZOJ 2112 Dynamic Rankings、codeforces 813E Army Creation、codeforces960F:Pathwalks )
在今天三黑(恶意评分刷上去的那种)两紫的智推中,突然出现了P3834 [模板]可持久化线段树 1(主席树)就突然有了不详的预感2333 果然...然后我gg了!被大佬虐了! hdu 2665 Kth ...
- 整体二分(SP3946 K-th Number ZOJ 2112 Dynamic Rankings)
SP3946 K-th Number (/2和>>1不一样!!) #include <algorithm> #include <bitset> #include & ...
- ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- ZOJ 2112 Dynamic Rankings(主席树の动态kth)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings ...
- ZOJ - 2112 Dynamic Rankings(BIT套主席树)
纠结了好久的一道题,以前是用线段树套平衡树二分做的,感觉时间复杂度和分块差不多了... 终于用BIT套函数式线段树了过了,120ms就是快,此题主要是卡内存. 假设离散后有ns个不同的值,递归层数是l ...
- BZOJ 1901 洛谷 P2617 ZOJ 2112 Dynamic Rankings
以下时空限制来自zoj Time limit 10000 ms Memory limit 32768 kB OS Linux Source Online Contest of Christopher' ...
- zoj 2112 Dynamic Rankings(主席树&动态第k大)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
随机推荐
- [转](多实例)mysql-mmm集群
一.需求说明 最近一直在学习mysql-mmm,想以后这个架构也能用在我们公司的业务上,我们公司的业务是单机多实例部署,所以也想把mysql-mmm部署成这样,功夫不负有心人,我成功了,和大家分享一下 ...
- 《C++ Primer 4th》读书笔记 第5章-表达式
原创文章,转载请注明出处: http://www.cnblogs.com/DayByDay/p/3912114.html
- jvm内部现成运行
hi,all 最近抽时间把JVM运行过程中产生的一些线程进行了整理,主要是围绕着我们系统jstack生成的文件为参照依据. 前段时间因为系统代码问题,造成性能瓶颈,于是就dump了一份stack出来 ...
- AFNetworking教程
转:http://www.lanrenios.com/tutorials/network/2012/1126/527.html AFNETWORKING AFNetworking他是一个现在非常用得多 ...
- 为在MyEclipse中配置Tomcat服务器郁闷的朋友们解决郁闷
是不是很郁闷!为了在MyEclipse配置Tomcat 服务器,竟然弄了你几乎一个上午,最后也没弄成功,也许你本该早注意到Tomcat 5.x要有这个JDK的支持,配置才能成功. 一上午辛辛苦苦也没解 ...
- 【c++内存分布系列】单独一个类
首先要明确类型本身是没有具体地址的,它是为了给编译器生成相应对象提供依据.只有编译器生成的对象才有明确的地址. 一.空类 形如下面的类A,类里没有任何成员变量,类的sizeof值为1. #includ ...
- Spring分布式事务实现
分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持.如果使用 ...
- useful-scripts
最近在github看到关于一些比较好的java相关脚本.vcs脚本.shell脚本.怕以后忘记了,在此做个备注. 原链接为:https://github.com/oldratlee/useful-sc ...
- webdriver(python)学习笔记四——定位一组元素
webdriver可以很方便的使用find_element方法来定位某个特定的对象,不过有时候我们却需要定位一组对象,这时候就需要使用find_elements方法. 定位一组对象一般用于以下场景: ...
- Tableau学习笔记之三
1.Tableau可以连接多种多样的数据以及数据库,例如txt,xls,mdb,sql server,oracle等等 2.Tableau还可以从剪贴板上粘贴数据 3.维度和度量的理解: 1)维度即表 ...