# Luogu3380 二逼平衡树

## Description

1. 查询$k$在区间内的排名
2. 查询区间内排名为$k$的值
3. 修改某一位值上的数值
4. 查询$k$在区间内的前驱(前驱定义为严格小于x，且最大的数，若不存在输出-2147483647)
5. 查询$k$在区间内的后继(后继定义为严格大于x，且最小的数，若不存在输出2147483647)

## Code

#include <bits/stdc++.h>

using namespace std;

#define fst first
#define snd second
#define mp make_pair
#define squ(x) ((LL)(x) * (x))
#define debug(...) fprintf(stderr, __VA_ARGS__)

typedef long long LL;
typedef pair<int, int> pii;

template<typename T> inline bool chkmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; }
template<typename T> inline bool chkmin(T &a, const T &b) { return a > b ? a = b, 1 : 0; }

int sum = 0, fg = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') fg = -1;
for (; isdigit(c); c = getchar()) sum = (sum << 3) + (sum << 1) + (c ^ 0x30);
return fg * sum;
}

const int maxn = 5e4 + 10;
const int inf = 1e8;

pii operator + (const pii &a, const pii &b) { return mp(a.fst + b.fst, a.snd + b.snd); }

struct node {
int ls, rs, v;
}A[maxn * 444];

struct sts {
int a[16], cnt;
sts(): cnt(0) { }
void ins(int x) { a[++cnt] = x; }
sts ls() {
sts res; res.cnt = cnt;
for (int i = 1; i <= cnt; i++) res.a[i] = A[a[i]].ls;
return res;
}
sts rs() {
sts res; res.cnt = cnt;
for (int i = 1; i <= cnt; i++) res.a[i] = A[a[i]].rs;
return res;
}
int sum() {
int res = 0;
for (int i = 1; i <= cnt; i++) res += A[a[i]].v;
return res;
}
};

int rt[maxn];
namespace ST {
int cnt;
void change(int &rt, int l, int r, int x, int v) {
if (!rt) rt = ++cnt; A[rt].v += v;
if (l == r) return;
int mid = (l + r) >> 1;
if (x <= mid) change(A[rt].ls, l, mid, x, v);
else change(A[rt].rs, mid + 1, r, x, v);
}
pii query(sts a, sts b, int l, int r, int x) {
if (l == r) return mp(0, b.sum() - a.sum());
int mid = (l + r) >> 1;
int tot = (b.ls()).sum() - (a.ls()).sum();
if (x <= mid) return query(a.ls(), b.ls(), l, mid, x);
return mp(tot, 0) + query(a.rs(), b.rs(), mid + 1, r, x);
}
int rank(sts a, sts b, int l, int r, int k) {
if (l == r) return l;
int mid = (l + r) >> 1;
int tot = (b.ls()).sum() - (a.ls()).sum();
if (k <= tot) return rank(a.ls(), b.ls(), l, mid, k);
return rank(a.rs(), b.rs(), mid + 1, r, k - tot);
}
}

int n, m, a[maxn];

namespace BIT {
#define lowbit(x) ((x) & -(x))
void change(int x, int v, int op) {
for (int i = x; i <= n; i += lowbit(i))
ST::change(rt[i], 0, inf, v, op);
}
pii query(int l, int r, int k) {
sts L, R;
for (int i = r; i; i -= lowbit(i)) R.ins(rt[i]);
for (int i = l - 1; i; i -= lowbit(i)) L.ins(rt[i]);
return ST::query(L, R, 0, inf, k);
}
int rank(int l, int r, int k) {
sts L, R;
for (int i = r; i; i -= lowbit(i)) R.ins(rt[i]);
for (int i = l - 1; i; i -= lowbit(i)) L.ins(rt[i]);
return ST::rank(L, R, 0, inf, k);
}
}

int main() {
#ifdef xunzhen
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
#endif

for (int i = 1; i <= n; i++) BIT::change(i, a[i] = read(), 1);

for (int i = 1; i <= m; i++) {
if (op == 1) {
printf("%d\n", BIT::query(l, r, k).fst + 1);
}
if (op == 2) {
printf("%d\n", BIT::rank(l, r, k));
}
if (op == 3) {
BIT::change(x, a[x], -1), BIT::change(x, a[x] = read(), 1);
}
if (op == 4) {
pii res = BIT::query(l, r, x);
if (res.fst) printf("%d\n", BIT::rank(l, r, res.fst));
else printf("-2147483647\n");
}
if (op == 5) {
}