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的更多相关文章

  1. ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)

    题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...

  2. 整体二分&cdq分治 ZOJ 2112 Dynamic Rankings

    题目:单点更新查询区间第k大 按照主席树的思想,要主席树套树状数组.即按照每个节点建立主席树,然后利用树状数组的方法来更新维护前缀和.然而,这样的做法在实际中并不能AC,原因即卡空间. 因此我们采用一 ...

  3. 主席树[可持久化线段树](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 ...

  4. 整体二分(SP3946 K-th Number ZOJ 2112 Dynamic Rankings)

    SP3946 K-th Number (/2和>>1不一样!!) #include <algorithm> #include <bitset> #include & ...

  5. ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  6. ZOJ 2112 Dynamic Rankings(主席树の动态kth)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings ...

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

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

  8. BZOJ 1901 洛谷 P2617 ZOJ 2112 Dynamic Rankings

    以下时空限制来自zoj Time limit 10000 ms Memory limit 32768 kB OS Linux Source Online Contest of Christopher' ...

  9. zoj 2112 Dynamic Rankings(主席树&amp;动态第k大)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

随机推荐

  1. <六>面向对象分析之UML核心元素之业务实体

    一:基本概念

  2. 【树状数组(二叉索引树)】轻院热身—candy、NYOJ-116士兵杀敌(二)

    [概念] 转载连接:树状数组 讲的挺好. 这两题非常的相似,查询区间的累加和.更新结点.Add(x,d) 与 Query(L,R) 的操作 [题目链接:candy] 唉,也是现在才发现这题用了这个知识 ...

  3. 数据来自后台非Ajax加载的联动实现方法

    要实现的效果如下,通过一级标签来控制二级标签, 第一步:在Conctroller中获取数据,并且请到modle里面返回 ModelAndView model = new ModelAndView(&q ...

  4. 本博客迁移到Github,之后停止更新

    本博客之后停止更新或者更新不是很及时,关注博客请移步   http://waylife.github.io 或者 http://blog.13kbook.com   谢谢支持. Update Time ...

  5. HDU 2056 Rectangles

    Rectangles Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. Oracle EM 不能访问

    zwt2001267 原文 Oracle EM 不能访问 1. cmd控制启动EM: C:\Users\Administrator>emctl start dbconsoleEnvironmen ...

  7. 类装载器ClassLoader

    类装载器工作机制 类装载器就是寻找类的节码文件并构造出类在JVM内部表示对象的组件.在Java中,类装载器把一个类装入JVM中,要经过以下步骤: [1.]装载:查找和导入Class文件: [2.]链接 ...

  8. Linux--使用expect进行自动交互

    在linux下进行一些操作时,有时需要与机器进行一些交互操作,比如切换账号时输入账号密码,传输文件时输入账号密码登陆远程机器等,但有时候这些动作需要在shell脚本中进行,这个时候就可以使用expec ...

  9. <转>浅谈DNS体系结构:DNS系列之一

    浅谈DNS体系结构 DNS是目前互联网上最不可或缺的服务器之一,每天我们在互联网上冲浪都需要DNS的帮助.DNS服务器能够为我们解析域名,定位电子邮件服务器,找到域中的域控制器……面对这么一个重要的服 ...

  10. C++虚函数表原理

    C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指 向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技 ...