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. ActionBarSherlock的学习笔记(三) ------------ ActionBarSherlock中的overflow及item的点击事件

    定义一个自定义的ActionBar的title,并添加一个overflow的Action   Item. 代码实现 如下  : import android.os.Bundle; import and ...

  2. 也谈http中get和post

    1.get和post区别: 从设计初衷考虑get是为了查询服务器资源(不改变服务器数据及状态,因此说它是安全和幂等的,但get请求参数一般是直接在url后面,浏览器地址栏中会被看到能保存书签及历史记录 ...

  3. request的用法

    Request从几个集合取数据是有顺序的,从前到后的顺序依次是 QueryString,Form,最后是ServerVariables.Request对象按照这样的顺序依次搜索这几个集合中的变量,如果 ...

  4. 【转】http-equiv的含义

    http-equiv顾名思义,相当于http的文件头作用,它可以向浏览器传回一些有用的信息,以帮助正确和精确地显示网页内容,与之对应的属性值为content,content中的内容其实就是各个参数的变 ...

  5. UVALive 4255 Guess

    这题竟然是图论···orz 题意:给出一个整数序列a1,a2,--,可以得到如下矩阵 1 2 3 4 1 - + 0 + 2   + + + 3       -  - 4         + &quo ...

  6. 使用SQL语句清空数据库所有表的数据

    使用SQL语句清空数据库所有表的数据 近来发现数据库过大,空间不足,因此打算将数据库的数据进行全面的清理,但表非常多,一张一张的清空,实在麻烦,因此就想利用SQL语句一次清空所有数据.找到了三种方法进 ...

  7. (原创)LAMP教程6-使用SecureCRTPortable工具远程连接centos

    (原创)LAMP教程6-使用SecureCRTPortable工具远程连接centos 是的,今天老柯就给大家介绍一款可以远程连接centos的工具,是的这个就是目前,最夯实的,最多人使用的Secur ...

  8. 关于webpack最好的文档

    这几天研究webpack打包工具,在网上搜了无数的资料,鱼龙混杂.看了几十份资料,依然没有一个可以完整的描述的. 折腾了那么久,还是放弃治疗了.回到官网,一字一句的阅读,一个小时就彻底明白了. 学习新 ...

  9. 双网卡bond

           使用双网卡虚拟为一块网卡: 服务器版本: [root@kel ~]# lsb_release -a LSB Version: :core-3.1-amd64:core-3.1-ia32: ...

  10. PHP实现分页:文本分页和数字分页

    来源:http://www.ido321.com/1086.html 最近,在项目中要用到分页.分页功能是经常使用的一个功能,所以,对其以函数形式进行了封装. // 分页分装 /** * $pageT ...