动态区间询问kth,单点修改。

区间用线段树分解,线段树上每条线段存一颗平衡树。

不能直接得到kth,但是利用val和比val小的个数之间的单调性,二分值。log^3N。

修改则是一次logN*logN。

总体是Nlog^2N+Mlog^3N。

一个值可以对应多个名次。每次查询严格小于val的个数。

把之前的Treap的值域加了一个vs表示值的出现次数,这样就可以支持重复的val了,并可以统计出值出现次数。

这样每个值的名次就变成一个区间了。

复杂度更低的做法:树状数组套主席树,还不太会。

#include<bits/stdc++.h>
using namespace std; #define PS push
const int maxn = 5e4+;
const int LgN = , maxnds = maxn*LgN; namespace Treap
{
int r[maxnds],s[maxnds],v[maxnds],ch[maxnds][],vs[maxnds];
const int nil = , chsz = sizeof(ch[]);
#define CLRch(x) memset(ch[x],0,chsz);
stack<int> meos;
void Treap_init(){
for(int i = maxnds; --i; ){
meos.PS(i);
}
s[nil] = ;
} inline int newNode(int val){
int i = meos.top(); meos.pop();
r[i] = rand(); v[i] = val;
vs[i] = s[i] = ; CLRch(i)
return i;
} inline void delt(int i) { meos.PS(i); } #define lch ch[o][0]
#define rch ch[o][1] inline void mt(int o){
s[o] = s[lch] + s[rch] + vs[o];
}
inline int cmp(int a,int b){
return a == b?-:(a>b?:);
} inline void rot(int &o,int d){
int k = ch[o][d^];
ch[o][d^] = ch[k][d];
ch[k][d] = o;
mt(o); mt(k);
o = k;
} int qval;
void inst(int &o){
if(!o){
o = newNode(qval);
}else {
int d = cmp(v[o],qval);
if(!~d) {
s[o]++; vs[o]++; return;
}
inst(ch[o][d]);
if(r[ch[o][d]] > r[o]) rot(o,d^);
else mt(o);
}
} void rmov(int &o){
int d = cmp(v[o],qval);
if(!~d){
if(vs[o] > ) {
s[o]--; vs[o]--; return;
}
if(!lch){
delt(o);
o = rch;
}else if(!rch){
delt(o);
o = lch;
}else {
int d2 = r[lch] > r[rch] ? : ;
rot(o,d2);
rmov(ch[o][d2]);
}
}else{
rmov(ch[o][d]);
}
if(o) mt(o);
} void clrTree(int &o){
if(lch) clrTree(lch);
if(rch) clrTree(rch);
delt(o);
o = nil;
}
int Finded;
int Order(int &o){
if(!o) return ;
int d = cmp(v[o],qval);
if(!~d){
Finded += vs[o];
return s[lch];
}else{
return (d?s[lch]+vs[o]:) + Order(ch[o][d]);
}
}
} using namespace Treap; int rt[maxn<<]; int a[maxn];
int n; #define para int o = 1, int l = 1,int r = n
#define lo (o<<1)
#define ro (o<<1|1)
#define TEMP int mid = (l+r)>>1;
#define lsn lo, l, mid
#define rsn ro, mid+1, r
#define insd ql<=l&&r<=qr
int ql,qr,val; void build(para)
{
if(rt[o]) clrTree(rt[o]);
for(int i = l; i <= r; i++){
qval = a[i]; inst(rt[o]);
}
if(l == r) return;
else {
TEMP
build(lsn);
build(rsn);
}
} int query(para)
{
if(insd){
return Order(rt[o]);
}else {
TEMP
int re = ;
if(ql<=mid) re += query(lsn);
if(qr>mid) re += query(rsn);
return re;
}
} int qpos;
void Change(para)
{
qval = a[qpos];
rmov(rt[o]);
qval = val;
inst(rt[o]);
if(l < r){
TEMP
if(qpos <= mid) Change(lsn);
else Change(rsn);
}
} //#define LOCAL
int main()
{
#ifdef LOCAL
freopen("data.txt","r",stdin);
#endif
int T; scanf("%d",&T);
Treap_init();
while(T--){
int m; scanf("%d%d",&n,&m);
int low = 1e9, high = ;
for(int i = ; i <= n; i++) {
scanf("%d",a+i);
low = min(a[i],low);
high = max(a[i],high);
}
build();
while(m--){
char op[];
int x,y;
scanf("%s%d%d",op,&x,&y);
if(*op == 'Q'){
ql = x; qr = y;
int k; scanf("%d",&k);
int L = low,R = high;
while(L<R){
int M = (L+R+)>>;
qval = M;
Finded = ;
int re = query();
if(k <= re) R = M-;
else if(k > re+Finded) L = M+;
else { L = M; break; }
}
printf("%d\n",L);
}else {
qpos = x;
val = y;
Change();
a[qpos] = y;
low = min(y,low);
high = max(y,high);
}
}
}
return ;
}

ZOJ 2112 Dynamic Rankings(二分,树套树)的更多相关文章

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

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

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

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

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

  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 大+块状链表)

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

  6. zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap

    Dynamic Rankings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/show ...

  7. BZOJ 1901 洛谷 P2617 ZOJ 2112 Dynamic Rankings

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

  8. ●ZOJ 2112 Dynamic Rankings

    ●赘述题目 对于一个长为n(n<50000)的序列(序列中的数小于1000000000),现有如下两种指令: Q a b c:询问区间[a,b]中第c小的数. C p b:将序列中的从左往右数第 ...

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

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

  10. ZOJ 2112 Dynamic Rankings (动态第 K 大)(树状数组套主席树)

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

随机推荐

  1. 2010辽宁省赛E(Bellman_Ford最短路,状态压缩DP【三进制】)

    #include<bits/stdc++.h>using namespace std;const int inf=0x3f3f3f3f;struct node{    int v,z,d, ...

  2. servlet之doPost()、doGet()

    1.doGet和doPost方法的具体应用?即在什么时候程序调用doGet方法,什么时候程序执行doPost方法? HttpServlet是从GenericServlet继承而来,因此HttpServ ...

  3. Openstack swift 学习笔记

    Swift 不是文件系统或者实时的数据存储系统,而是对象存储,用于长期存储永久类型的静态数据.这些数据可以检索.调整和必要时进行更新.Swift最适合虚拟机镜像.图片.邮件和存档备份这类数据的存储. ...

  4. 洛谷P1066 2^k进制数

    P1066 2^k进制数 题目描述 设r是个2^k 进制数,并满足以下条件: (1)r至少是个2位的2^k 进制数. (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位. ( ...

  5. Mysql缓存的配置和使用

    在mysql服务器高负载的情况下,必须采取一种措施给服务器减轻压力,减少服务器的I/O操作.一般采用的方法是优化sql操作语句,优化服务器的配置参数,从而提高服务器的性能.Mysql使用了几种内存缓存 ...

  6. django进阶之缓存

    Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...

  7. Codeforces Round #499 (Div. 1)部分题解(B,C,D)

    Codeforces Round #499 (Div. 1) 这场本来想和同学一起打\(\rm virtual\ contest\)的,结果有事耽搁了,之后又陆陆续续写了些,就综合起来发一篇题解. B ...

  8. thinkphp5更新时验证数据

    在编辑页面form表单中添加一个隐藏域:<input type="hidden" name="表中id字段名" value="get方式传过来的 ...

  9. rem字体在rem盒子里面不一样,或者不同的行解决

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. js index of()用法

    含义: indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置.(工作中常用) 提示和注释: 注释:indexOf() 方法对大小写敏感! 注释:如果要检索的字符串值没有出现,则该方 ...