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;
}