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

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.

题目大意:给n个数,有m个操作。修改某个数,或者询问一段区间的第k小值。

思路:首先要知道没有修改操作的区间第k大怎么用出席树写:POJ 2104 K-th Number(主席树——附讲解)

至于动态kth的解法可以去看CLJ的《可持久化数据结构研究》(反正我是看这个才懂的),然后在网上查一些资料,YY一下就可以了。

这里写的是树状数组套线段树+可持久化线段树的做法(因为内存不够用)。

简单的讲就是通过树状数组求和,维护前k个线段树的和。时间复杂度为O(nlogn+m(logn)^2)

另参考资料(里面有好几个link :)):http://www.cnblogs.com/kuangbin/p/3308118.html

PS:ZOJ的指针似乎不是4个字节的。这里用指针就要MLE了(代码本来不是这么丑的啊T_T)。

代码(130MS):

 #include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXM = ;
const int MAXT = MAXM * * ; struct Query {
char op;
int i, j, k;
void read() {
scanf(" %c", &op);
if(op == 'Q') scanf("%d%d%d", &i, &j, &k);
else scanf("%d%d", &i, &k);
}
} query[MAXM];
int a[MAXN];
int n, m, T;
//hashmap
int arr[MAXN + MAXM], total; void buildHash() {
total = ;
for(int i = ; i <= n; ++i) arr[total++] = a[i];
for(int i = ; i <= m; ++i)
if(query[i].op == 'C') arr[total++] = query[i].k;
sort(arr, arr + total);
total = unique(arr, arr + total) - arr;
} int hash(int x) {
return lower_bound(arr, arr + total, x) - arr;
}
//Chairman tree
struct Node {
int lson, rson, sum;
void clear() {
lson = rson = sum = ;
}
} tree[MAXT];
int root[MAXN];
int tcnt; void insert(int& rt, int l, int r, int pos) {
tree[tcnt] = tree[rt]; rt = tcnt++;
tree[rt].sum++;
if(l < r) {
int mid = (l + r) >> ;
if(pos <= mid) insert(tree[rt].lson, l, mid, pos);
else insert(tree[rt].rson, mid + , r, pos);
}
} void buildTree() {
tcnt = ;
for(int i = ; i <= n; ++i) {
root[i] = root[i - ];
insert(root[i], , total - , hash(a[i]));
}
}
//Binary Indexed Trees
int root2[MAXN];
int roota[], rootb[];
int cnta, cntb; void initBIT() {
for(int i = ; i <= n; ++i) root2[i] = ;
} inline int lowbit(int x) {
return x & -x;
} void insert(int& rt, int l, int r, int pos, int val) {
if(rt == ) tree[rt = tcnt++].clear();
if(l == r) {
tree[rt].sum += val;
} else {
int mid = (l + r) >> ;
if(pos <= mid) insert(tree[rt].lson, l, mid, pos, val);
else insert(tree[rt].rson, mid + , r, pos, val);
tree[rt].sum = tree[tree[rt].lson].sum + tree[tree[rt].rson].sum;
}
} int kth(int ra, int rb, int l, int r, int k) {
if(l == r) {
return l;
} else {
int sum = tree[tree[rb].lson].sum - tree[tree[ra].lson].sum, mid = (l + r) >> ;
for(int i = ; i < cntb; ++i) sum += tree[tree[rootb[i]].lson].sum;
for(int i = ; i < cnta; ++i) sum -= tree[tree[roota[i]].lson].sum;
if(sum >= k) {
for(int i = ; i < cntb; ++i) rootb[i] = tree[rootb[i]].lson;
for(int i = ; i < cnta; ++i) roota[i] = tree[roota[i]].lson;
return kth(tree[ra].lson, tree[rb].lson, l, mid, k);
} else {
for(int i = ; i < cntb; ++i) rootb[i] = tree[rootb[i]].rson;
for(int i = ; i < cnta; ++i) roota[i] = tree[roota[i]].rson;
return kth(tree[ra].rson, tree[rb].rson, mid + , r, k - sum);
}
}
}
//Main operation
void modify(int k, int val) {
int x = hash(a[k]), y = hash(val);
a[k] = val;
while(k <= n) {
insert(root2[k], , total - , x, -);
insert(root2[k], , total - , y, );
k += lowbit(k);
}
} int kth(int l, int r, int k) {
cnta = cntb = ;
for(int i = l - ; i; i -= lowbit(i)) roota[cnta++] = root2[i];
for(int i = r; i; i -= lowbit(i)) rootb[cntb++] = root2[i];
return kth(root[l - ], root[r], , total - , k);
} int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for(int i = ; i <= n; ++i) scanf("%d", &a[i]);
for(int i = ; i <= m; ++i) query[i].read();
buildHash();
buildTree();
initBIT();
for(int i = ; i <= m; ++i) {
if(query[i].op == 'Q') printf("%d\n", arr[kth(query[i].i, query[i].j, query[i].k)]);
else modify(query[i].i, query[i].k);
}
}
}

ZOJ 2112 Dynamic Rankings(主席树の动态kth)的更多相关文章

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

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

  2. ZOJ -2112 Dynamic Rankings 主席树 待修改的区间第K大

    Dynamic Rankings 带修改的区间第K大其实就是先和静态区间第K大的操作一样.先建立一颗主席树, 然后再在树状数组的每一个节点开线段树(其实也是主席树,共用节点), 每次修改的时候都按照树 ...

  3. ZOJ 2112 Dynamic Rankings(树状数组+主席树)

    题意 \(n\) 个数,\(m\) 个操作,每次操作修改某个数,或者询问某个区间的第 \(K\) 小值. \(1 \leq n \leq 50000\) \(1 \leq m \leq 10000\) ...

  4. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

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

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

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

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

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

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

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

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

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

随机推荐

  1. WIN10 ANDROIDSTUDIO1.2 安装完首次启动报错

    环境 ACER NOTEBOOK  WIN10 ANNDROID 1.2 解决方案: 在Android Studio安装目录下的 bin 目录下,找到 idea.properties 文件,在文件最后 ...

  2. 64 位win 7或windows 8下的visual studio不能连接Oracle数据库调试网站的问题

    在64 位win 7或windows 8系统下,visual studio直接F5运行网站调试,你会发现不能连接Oracle数据库,会报一个“ORA-06413: Connection not ope ...

  3. HBase学习笔记-高级(一)

    HBase1. hbase.id记录了集群的唯一标识:hbase.version记录了文件格式的版本号2. split和.corrupt目录在日志分裂过程中使用,以便保存一些中间结果和损坏的日志在表目 ...

  4. 【Java 基础篇】【第八课】package包

    学习Java以来,第一次感觉稍微有点不好理解的,下面说说吧. 存在意义: 包的存在就是为更好的组织结构 包的创建: 只要在程序的最前面加入 Package ******,就可以了,一般都喜欢写 com ...

  5. WPF自定义RoutedEvent事件示例代码

    ************************* 引用网友,便于查找所用..... 创建自定义路由事件和应用分为6个步骤: (1)自定义路由事件参数对象 (2)声明并注册路由事件 (3)为路由事件添 ...

  6. 用户交互与while循环<代码>

    #用户交互1 age_oldboy = 56 guess_age = int(input(">>:")) if guess_age == age_oldboy: pri ...

  7. 20145211 《Java程序设计》实验报告三:敏捷开发与XP实践

    实验内容 使用 git上传代码 使用 git相互更改代码 实现代码的重载 XP基础 XP核心实践 相关工具 一.git上传代码 这一部分是与我的partner合作的,详见他的博客- 20145326蔡 ...

  8. pickle 数据对象的序列化和反序列化

    python的pickle模块实现了基本的数据序列和反序列化.通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储:通过pickle模块的反序列化操作,我们能够从文件 ...

  9. <dependency>spring-webmvc</dependency>

    Spring 4.2.0.RELEASE版本: <dependency> <groupId>org.springframework</groupId> <ar ...

  10. Java私有构造函数不能阻止继承

    下面是一个调用已经私有化的单列的函数的列子. 这里用了静态内部类,关键就是静态内部类可以访问外部类的私有构造函数. 这种算是变种继承吧.前提是可以在原来的单列类里添加代码. class Single ...