给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。
Input
输入描述:
第一行包含一个数n,表示序列长度。
第二行包含n个正整数,表示给定的序列。
第三个包含一个正整数m,表示询问个数。
接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。
输入样例:
5
1 2 3 4 5
2
1 5 2
2 3 2
Output
输出描述:
总共输出m行,每行一个数,表示询问的答案。
输出样例:
4
2
#define _CRT_SBCURE_NO_DEPRECATE
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define maxn 100005
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
vector<int> T[maxn << 2];
int N, Q;
void build(int l, int r, int rt) {
if(l == r) {
int val;
scanf("%d", &val);
// 从左到右的每个子节点
T[rt].push_back(val);
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
T[rt].resize(r - l + 1); // 注意父节点的大小
merge(T[rt<<1].begin(), T[rt<<1].end(), T[rt<<1|1].begin(), T[rt<<1|1].end(), T[rt].begin());
}
// 计算[L,R]中小于等于val的个数
int query(int L, int R, int val, int l, int r, int rt) {
if(L == l && R == r) {
// 返回不超过val的个数
return upper_bound(T[rt].begin(), T[rt].end(), val) - T[rt].begin();
}
int mid = (l + r) >> 1;
if(R <= mid) return query(L, R, val, lson);
else if(L > mid) return query(L, R, val, rson);
return query(L, mid, val, lson) + query(mid + 1, R, val, rson);
}
int main() {
// 提升读写速度
ios::sync_with_stdio(false);
cin.tie(0);
int a, b, c, k, left, right, mid;
scanf("%d", &N);
build(1, N, 1);
scanf("%d", &Q);
while(Q--) {
scanf("%d%d%d", &a, &b, &k);
left = -1; right = N - 1;
k = b - a + 2 - k;
while(right - left > 1) { // 在T[1]的 0 - N-1 中进行二分搜索
mid = (left + right) >> 1;
// 第一个节点是都排序好的
// 返回c为[a,b]区间中小于等于T[1][mid]的个数
c = query(a, b, T[1][mid], 1, N, 1);
if(c >= k) right = mid;
else left = mid;
}
printf("%d\n", T[1][right]);
}
return 0;
}