求区间第K大,很简单——-主席树即可;
那么如果增加一个修改操作,又该怎么处理呢?
单点修改—-很容易想到 树状数组;
此时树状数组每个节点存的是一颗空树;
详细的解释,说明
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#pragma GCC optimize("O3")
using namespace std;
#define maxn 60005
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
typedef long long ll;
typedef unsigned long long ull;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define sq(x) (x)*(x)
#define eps 1e-6
const int N = 2500005;
inline int read()
{
int x = 0, k = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-')k = -1; c = getchar(); }
while (c >= '0' && c <= '9')x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
return x * k;
}
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a%b);
}
int a[maxn], b[maxn], rt[maxn], num, f[maxn], used[maxn];
int cnt, sum[N], ls[N], rs[N], n, q[10005][4];
void build(int &id, int l, int r) {
id = ++cnt;
sum[id] = 0;
if (l == r)return;
int mid = (l + r)/2;
build(ls[id], l, mid); build(rs[id], mid + 1, r);
}
void upd(int &id, int l, int r, int last, int val, int k) {
id = ++cnt;
ls[id] = ls[last]; rs[id] = rs[last];
sum[id] = sum[last] + k;
if (l == r)return;
int mid = (l + r) /2;
if (val <= mid)
upd(ls[id], l, mid, ls[last], val, k);
else
upd(rs[id], mid + 1, r, rs[last], val, k);
}
int Sum(int x) {
int ans = 0;
while (x) {
ans += sum[ls[used[x]]];
x -= x & -x;
}
return ans;
}
int query(int st, int ed, int val) {
int i, les, res;
int l = 1, r = num;
les = rt[st]; res = rt[ed];
for (i = st; i > 0; i -= i & -i)used[i] = f[i];
for (i = ed; i > 0; i -= i & -i)used[i] = f[i];
while (l < r) {
int mid = (l + r)>>1;
int tmp = Sum(ed) - Sum(st) + sum[ls[res]] - sum[ls[les]];
if (val <= tmp) {
r = mid;
for (i = st; i > 0; i -= i & -i) {
used[i] = ls[used[i]];
}
for (i = ed; i > 0; i -= i & -i) {
used[i] = ls[used[i]];
}
les = ls[les]; res = ls[res];
}
else {
l = mid + 1; val -= tmp;
for (i = st; i > 0; i -= i & -i)used[i] = rs[used[i]];
for (i = ed; i > 0; i -= i & -i)used[i] = rs[used[i]];
les = rs[les]; res = rs[res];
}
}
return l;
}
void add(int x, int v, int k) {
while (x<=n)
{
int tmp = f[x];
upd(f[x], 1, num, tmp, v, k); x += x & -x;
}
}
int main()
{
char c;
int T, m, i, j;
cin >> T;
while (T--) {
cnt = 0;
//ms(sum);
memset(sum, 0, sizeof(sum));
cin >> n >> m;
for (i = 1; i <= n; i++) {
scanf("%d", &a[i]); b[i] = a[i];
}
num = n;
for (i = 1; i <= m; i++) {
cin >> c;
if (c == 'Q') {
//q[i][1] = read(); q[i][2] = read(); q[i][3] = read();
scanf("%d%d%d", &q[i][1], &q[i][2], &q[i][3]);
q[i][0] = 1;
}
else {
q[i][1] = read(); q[i][2] = read();
b[++num] = q[i][2]; q[i][0] = 0;
}
}
sort(b + 1, b + num + 1);
num = unique(b + 1, b + num + 1) - b - 1;
for (i = 1; i <= num; i++) {
a[i] = lower_bound(b + 1, b + num + 1, a[i]) - b;
}
build(rt[0], 1, num);
for (i = 1; i <= n; i++) {
upd(rt[i], 1, num, rt[i - 1], a[i], 1);
}
for (i = 1; i <= n; i++)f[i] = rt[0];
for (i = 1; i <= m; i++) {
if (q[i][0]==1) {
int ans = query(q[i][1] - 1, q[i][2] , q[i][3]);
//cout << b[ans] << endl;
printf("%d\n", b[ans]);
}
else {
int tmp;
add(q[i][1], a[q[i][1]], -1);
tmp = lower_bound(b + 1, b + num + 1,q[i][2]) - b;
add(q[i][1], tmp, 1);
a[q[i][1]] = tmp;
}
}
}
return 0;
}