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 ...
随机推荐
- 构造函数后面的base()
先执行父类的对应的构造函数,再执行当前的构造函数. 关于子类对象的构造函数和父类构造函数的执行顺序 以下内容转自:http://blog.csdn.net/todototry/article/deta ...
- 9月5日 华为2014校园招聘的机试题目_C语言版答案
手有些生了. 题目: 通过键盘输入一串小写字母(a~z)组成的字符串.请编写一个字符串压缩程序,将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串.压缩规则:1.仅压缩连续重复出现的字符.比如 ...
- bjfu1097 图标排列
这是2011年百度之星的一道题.这题的做法就是找规律,规律找对了,代码极水.规律我一开始也没有找到,后来经人提醒,发现如下规律:对于每个开发者,其所有应用的分离度和一定是其第一个应用与最后一个应用的距 ...
- virtualbox虚拟机中mysql远程连接登陆报2003错误的解决方法
最近在virtualbox中安装了Ubuntu 14,配置了一个mysql server,设置的桥接网络模式.在其他电脑连接的时候,总是报2003错误.开始以为是localhost没有置换为%,运行u ...
- C++实现网格水印之调试笔记(一)
首先说一下我的一些简单的调试方法,除了常规的断点调试之外,我还会使用注释的方法来调试.当整个工程代码量相当多且调用层次关系较为复杂时,这种方法能够比较高效的定位到出错误的代码段或某个函数,然后在出现错 ...
- WebStorm2016.1 破解 激活
WebStorm2016.1 破解 激活 方法来自 Rover12421 大神. 1.从官网下载WebStorm2016.1安装. 2.下载 破解补丁 并解压,记住路径 3.编辑WebStorm安 ...
- 初识HTML 5:关于它的三个三
来源:http://www.ido321.com/949.html 一.HTML 5受欢迎的三个理由 1.IE.Google.Firefox.Safari.Opera等主流浏览器的支持 1.1 微软 ...
- 浅谈JavaScript中的原型模式
在JavaScript中创建对象由很多种方式,如工厂模式.构造函数模式.原型模式等: <pre name="code" class="html">/ ...
- codeforce 702C Cellular Network 二分答案
http://codeforces.com/contest/702 题意:n个村庄,m个机站,问机站最短半径覆盖完所有村庄 思路:直接二分答案 二分太弱,调了半天..... // #pragma co ...
- C++11 之 " = delete "
1 缺省函数 设计一个类,没有成员函数 (member function),只有成员数据 (member data) class DataOnly { private: std::string st ...