ZOJ2112-Dynamic Rankings

来源:互联网 发布:异地同步看电影软件 编辑:程序博客网 时间:2024/06/10 21:22

Dynamic Rankings

Time Limit: 10 Seconds      Memory Limit: 32768 KB

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


(adviser)
Site: http://zhuzeyuan.hp.infoseek.co.jp/index.files/our_contest_20040619.htm


Author: XIN, Tao
Source: Online Contest of Christopher's Adventure


题意:给你一个序列,有n个数,两种操作,Q:询问在[l,r]内的第k大的数,C:更改第i个数位x

解题思路:主席数保存初始序列,树状数组+线段树记录修改操作


#include <iostream>  #include <cstdio>  #include <cstring>  #include <string>  #include <algorithm>  #include <cctype>  #include <map>  #include <cmath>  #include <set>  #include <stack>  #include <queue>  #include <vector>  #include <bitset>  #include <functional>  using namespace std;#define LL long long  const int INF = 0x3f3f3f3f;const int maxn = 60505;const int maxm = 1000505;const int lowbit(int k) { return k&-k; }int t, n, m, q, a[maxn], b[maxn], c[maxn], tot1, tot2;char ch[2];int L1[maxm], R1[maxm], sum1[maxm], s1[maxn];int L2[maxm], R2[maxm], sum2[maxm], s2[maxn];struct node{int f, l, r, k;}p[maxn];void build(int pre, int &now, int l, int r, int k){sum1[now = ++tot1] = sum1[pre] + 1;if (l == r) { L1[now] = R1[now] = 0; return; }int mid = (l + r) >> 1;L1[now] = L1[pre], R1[now] = R1[pre];if (mid >= k) build(L1[pre], L1[now], l, mid, k);else build(R1[pre], R1[now], mid + 1, r, k);}void add(int &k, int l, int r, int p, int val){if (!k) k = ++tot2, L2[k] = R2[k] = sum2[k] = 0;sum2[k] += val;if (l == r) return;int mid = (l + r) >> 1;if (p <= mid) add(L2[k], l, mid, p, val);else add(R2[k], mid + 1, r, p, val);}void Insert(int k, int p, int val){for (int i = k; i <= n; i += lowbit(i)) add(s2[i], 1, m - 1, p, val);}int query(int l, int r, int k){int A = 0, B = 0, a[50], b[50], u = s1[l - 1], v = s1[r];for (int i = l - 1; i; i -= lowbit(i)) a[A++] = s2[i];for (int i = r; i; i -= lowbit(i)) b[B++] = s2[i];for (l = 1, r = m - 1; l < r;){int sum = 0, mid = (l + r) >> 1;for (int i = 0; i < B; i++) sum += sum2[L2[b[i]]];for (int i = 0; i < A; i++) sum -= sum2[L2[a[i]]];sum += sum1[L1[v]] - sum1[L1[u]];if (k <= sum){for (int i = 0; i < B; i++) b[i] = L2[b[i]];for (int i = 0; i < A; i++) a[i] = L2[a[i]];u = L1[u];  v = L1[v]; r = mid;}else{for (int i = 0; i < B; i++) b[i] = R2[b[i]];for (int i = 0; i < A; i++) a[i] = R2[a[i]];l = mid + 1, k -= sum, u = R1[u], v = R1[v];}}return l;}int main(){scanf("%d", &t);while (t--){scanf("%d%d", &n, &q);for (int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];int nn = n;for (int i = 1; i <= q; i++){scanf("%s", ch);if (ch[0] == 'Q') scanf("%d%d%d", &p[i].l, &p[i].r, &p[i].k), p[i].f = 1;else{p[i].f = 0, p[i].k = ++nn;scanf("%d%d", &p[i].l, &p[i].r);b[nn] = a[nn] = p[i].r;}}sort(a + 1, a + nn + 1);m = unique(a + 1, a + nn + 1) - a;for (int i = 1; i <= nn; i++) c[i] = lower_bound(a + 1, a + m, b[i]) - a;tot1 = L1[0] = R1[0] = sum1[0] = tot2 = s1[0] = 0;for (int i = 1; i <= n; i++) build(s1[i - 1], s1[i], 1, m - 1, c[i]);for (int i = 0; i <= n; i++) L2[i] = R2[i] = sum2[i] = 0;for (int i = 1; i <= q; i++){if (p[i].f){int ans = query(p[i].l, p[i].r, p[i].k);printf("%d\n", a[ans]);}else if (c[p[i].l] != c[p[i].k]){Insert(p[i].l, c[p[i].l], -1);Insert(p[i].l, c[p[i].k], 1);c[p[i].l] = c[p[i].k];}}}return 0;}

阅读全文
0 0
原创粉丝点击