离散化处理是将连续的数值离散化为一定数量的区间,常见的应用场景是处理区间询问问题。以下是一个简单的离散化处理算法模板:
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 100005;
int n, m, a[maxn], b[maxn], c[maxn];
int lowbit(int x) {
return x & (-x);
}
void add(int x, int k) {
while (x <= n) {
c[x] += k;
x += lowbit(x);
}
}
int sum(int x) {
int ans = 0;
while (x > 0) {
ans += c[x];
x -= lowbit(x);
}
return ans;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + n + 1);
int cnt = unique(b + 1, b + n + 1) - b - 1;
for (int i = 1; i <= n; i++) {
int x = lower_bound(b + 1, b + cnt + 1, a[i]) - b;
add(x, 1);
}
while (m--) {
int l, r, k;
scanf("%d%d%d", &l, &r, &k);
int L = 1, R = cnt;
while (L < R) {
int mid = (L + R) >> 1;
if (sum(mid) >= k) R = mid;
else L = mid + 1;
}
printf("%d\n", b[L]);
}
return 0;
}
具体做法如下:
将所有数值存入数组 b 中,对 b 数组进行排序并去重,记录去重后的数字个数 cnt。
对原数组中的每个数值求其在去重后的数组 b 中的下标 x,然后使用树状数组记录下标出现的次数。
对于每个查询区间 [l, r],二分区间中第 k 小的元素,然后根据元素在 b 数组中的下标,输出区间内第 k 小的数值。