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 ...
随机推荐
- 【有趣~】SFOJ-1711 Obey的恋爱、NYOJ-739 笨蛋难题
笨蛋难题四 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 这些日子笨蛋一直研究股票,经过调研,终于发现xxx公司股票规律,更可喜的是 笨蛋推算出这家公司每天的股价, ...
- 【转】第一次使用Android Studio时你应该知道的一切配置
原文网址:http://www.cnblogs.com/smyhvae/p/4390905.html [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.c ...
- 色谱峰的类型BB,BV,VB等都是什么意思
B(Baseline):峰在基线处开始或结束V(Valley):峰在谷点线处开始或结束P(Peak): 峰开始或结束与基线贯穿点BB就代表标准的峰:从基线开始出峰,最后峰到基线结束(from base ...
- linux命令——磁盘管理pwd
Linux中用 pwd 命令来查看”当前工作目录“的完整路径(绝对路径). 简单得说,每当你在终端进行操作时,你都会有一个当前工作目录.在不太确定当前位置时,就会使用pwd来判定当前目录在文件系统内的 ...
- ASP.NET单点登录(代码)
[p=25, null, left]由于某些原因,在我们的应用中会遇到一个用户只能在一个地方登录的情况,也就是我们通常所说的单点登录.在ASP.NET中实现单点登录其实很简单,下面就把主要的方法和全部 ...
- ORA-15018: diskgroup cannot be created
创建ASM磁盘组的时候出错,具体报错如下: SQL> create diskgroup kel external redundancy disk 'ORCL:KEL1','ORCL:KEL2'; ...
- 测试的rtsp地址
无线城市 千里眼 http://218.204.223.237:8081/wap/show_video.php?vd=1 右键->复制链接地址即可获得Rtsp地址.
- Python面向对象2
方法 公共方法 私有方法 类方法 静态方法 #!usr/bin/python #coding:utf8 class Milo(): name = 'csvt' def fun1(self): prin ...
- Tkinter教程之Listbox篇
本文转载自:http://blog.csdn.net/jcodeer/article/details/1811310 #Tkinter教程之Listbox篇#Listbox为列表框控件,它可以包含一个 ...
- 快速建立Linux c/c++编译环境
sudo apt-get install build-essential 省时又省心~