传送门
给定
l
,
r
l,r
l,r求区间第
k
k
k大,静态
分析
V下面有详解V
划分树解题报告
^上面有详解^
代码
//
/*
@Author: YooQ
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define sc scanf
#define pr printf
#define ll long long
#define int long long
#define FILE_OUT freopen("out", "w", stdout);
#define FILE_IN freopen("in", "r", stdin);
#define debug(x) cout << #x << ": " << x << "\n";
#define AC 0
#define WA 1
#define INF 0x3f3f3f3f
const ll MAX_N = 1e6+5;
const ll MOD = 1e9+7;
int N, M, K;
int arr[MAX_N];
int tr[30][MAX_N];
int toLeft[30][MAX_N];
void build(int l, int r, int d) {
if (l == r) return;
int mid = l + ((r-l)>>1);
int same = mid-l+1;
for (int i = l; i <= r; ++i) {
same -= tr[d][i] < arr[mid];
}
int lx = l, rx = mid+1;
for (int i = l; i <= r; ++i) {
if (tr[d][i] < arr[mid] || tr[d][i] == arr[mid] && same-- > 0) {
tr[d+1][lx++] = tr[d][i];
} else {
tr[d+1][rx++] = tr[d][i];
}
toLeft[d][i] = toLeft[d][l-1] + lx - l;
}
build(l, mid, d+1);
build(mid+1, r, d+1);
}
int query(int l, int r, int x, int y, int k, int d) {
if (x == y) {
return tr[d][x];
}
int mid = l + ((r-l)>>1);
int sum = toLeft[d][y] - toLeft[d][x-1];
int len = y - x + 1;
if (sum >= k) {
x = l + (toLeft[d][x-1] - toLeft[d][l-1]);
y = x + sum - 1;
return query(l, mid, x, y, k, d+1);
} else {
y = y + (toLeft[d][r] - toLeft[d][y]);
x = y - (len-sum) + 1;
return query(mid+1, r, x, y, k-sum, d+1);
}
}
void solve(){
sc("%lld%lld", &N, &M);
for (int i = 1; i <= N; ++i) {
sc("%lld", &arr[i]);
tr[0][i] = arr[i];
}
sort(arr+1, arr+1+N);
build(1, N, 0);
int l, r, k;
for (int i = 1; i <= M; ++i) {
sc("%lld%lld%lld", &l, &r, &k);
pr("%lld\n", query(1, N, l, r, k, 0));
}
}
signed main()
{
#ifndef ONLINE_JUDGE
//FILE_IN
FILE_OUT
#endif
int T = 1;//cin >> T;
while (T--) solve();
return AC;
}