题目链接: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. 蓝牙HID协议笔记

    1.概述     The Human Interface Device (HID)定义了蓝牙在人机接口设备中的协议.特征和使用规程.典型的应用包括蓝牙鼠标.蓝牙键盘.蓝牙游戏手柄等.该协议改编自USB ...

  2. Strom简介,以及安装,和官方案例测试

    一:简介 1.strom的两种形式 2.strom的特性 3.使用场景 4.集群架构 5.集群架构进程 6.组件 Nimbus 7.从节点Supervisor 8.组件worker 9.组件Execu ...

  3. Go 语言开发的基于 Linux 虚拟服务器的负载平衡平台 Seesaw

    负载均衡系统 Seesaw Seesaw是由我们网络可靠性工程师用 Go 语言开发的基于 Linux 虚拟服务器的负载平衡平台,就像所有好的项目一样,这个项目也是为了解决实际问题而产生的. Seesa ...

  4. linux下连接本地的navicate

    1.进mysql cd mysql; cd bin; ./mysql -uroot -proot; show databases;#可以没有 #修改权限 1.GRANT ALL PRIVILEGES ...

  5. 转: css box-sizing的用法

    當你設定一個元素樣式為 box-sizing: border-box;,這個元素的內距和邊框將不會增加元素本身的寬度. <!DOCTYPE html> <html lang=&quo ...

  6. PM2的使用

    PM2 是一个带有负载均衡功能的 Node 应用的进程管理器. 安装 npm install -g pm2 启动程序:pm2 start <app_name|id|all> 列举进程:pm ...

  7. Magento订单打印(pdf格式)

    Magento自身包含有:打印发票单,打印装箱单,打印退款单.这些都是基于西方国家的习惯来布置的.公司有个需求就是打印订单的四联单,PDF格式的,要一周内完成.刚接到这个任务时,觉得头大,因为对于PH ...

  8. 安装 zsh 、 on-my-zsh 和 autojump

    安装 zsh . on-my-zsh 和 autojump zsh 是 linux 上另外一个 shell ,号称是终极 shell .它的配置比较复杂,一般的发行版中,默认没有安装这个 shell ...

  9. Win32和MFC项目如何输出调试信息到VS的调试窗口

    直接举例说明: Win32项目: #include <Windows.h> OutputDebugString(TEXT("调试信息:MyCircleImpl::~MyCircl ...

  10. mysql 启动服务

    http://blog.chinaunix.net/uid-13642598-id-3153537.html mysql的四种启动方式: 1.mysqld 启动mysql服务器:./mysqld -- ...