k-th number
给定数列a1,a2…an,各不相同。要进行m次查询,每次查询 a[L…R] 中第k小的数是什么 (1 <= n <= 100 000, 1 <= m <= 5 000) abs(ai) <= 10^9
样例输入
7 3 //7个数,3次查询
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
样例输出
5
6
3
#include <iostream>
#include <algorithm>
using namespace std;
int Array[100002]; //Array记录原始数组
int order[100002]; //order记录数组中每个元素对应的编号(从小到大) 离散化
int sortA[100002]; //sortA用来对数组排序并记录
int p;
struct tree
{
int* store;
int len;
int l;
int r;
tree* left;
tree* right;
};
void buildtree(tree* root, int L, int R)
//将order数组第L到第R个元素,并将其排序后放入store数组中,方便之后用upper_bound函数进行二分查找
{
root->len = R - L + 1;
root->l = L;
root->r = R;
root->store = new int[root->len + 10];
for (int i = 1; i <= root->len; i++)
{
root->store[i] = order[L + i - 1];
}
sort(root->store, root->store + root->len + 1); //对store数组进行处理
root->left = new tree;
root->right = new tree;
if (L == R) //分解到了最底层
return;
int mid = (L + R) / 2;
buildtree(root->left, L, mid);
buildtree(root->right, mid + 1, R);
}
void quary(tree* root, int L, int R, int mid)
{
if (L == root->l&&R == root->r)
{
p += upper_bound(root->store + 1, root->store + root->len + 1, mid) - (root->store + 1);
//store数组已经排序,看这个子结点中比mid小或相等的元素有多少
return;
}
else
{
int Mid = (root->l + root->r) / 2;
if (R <= Mid)
quary(root->left, L, R, mid);
else if (L >= Mid + 1)
quary(root->right, L, R, mid);
else
{
quary(root->left, L, Mid, mid);
quary(root->right, Mid + 1, R, mid);
}
}
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> Array[i];
sortA[i] = Array[i];
}
sort(sortA + 1, sortA + n + 1);
for (int i = 1; i <= n; i++)
{
order[i] = lower_bound(sortA + 1, sortA + 1 + n, Array[i]) - sortA;
}
tree* root = new tree;
buildtree(root, 1, n);
while (m--)
{
int l, r;
int k;
cin >> l >> r >> k;
int tl = 1;
int tr = n;
if (l == r)
{
printf("%d\n", Array[l]);
continue;
}
int mid = (tl + tr) / 2;
while (1)
{
p = 0;
if (tl == tr)
{
printf("%d\n", sortA[tl]);
break;
}
quary(root, l, r, mid);
if (p >= k)
{
tr = mid;
mid = (tl + mid) / 2;
}
else
{
tl = mid + 1;
mid = (tr + mid) / 2;
}
}
}
return 0;
}