线段树二分第k大值
#include <bits/stdc++.h>
using namespace std;
const int maxn = 8e5 + 7;
int tree[maxn];
int l[maxn];
int r[maxn];
int a[maxn];
int b[maxn];
struct ope{
int k, p, ind;
}q[maxn];
int n, m;
int ans[maxn];
bool cmp (int x, int y)
{
return a[x - 1] == a[y - 1] ? x < y : a[x - 1] > a[y - 1];
}
bool cmp1 (ope &a, ope &b)
{
return a.k == b.k ? a.p < b.p : a.k < b.k;
}
void build (int v, int ll, int rr)
{
l[v] = ll;
r[v] = rr;
tree[v] = 0;
if(ll == rr)
return ;
int mid = ll + rr >> 1;
build(v * 2, ll, mid);
build(v * 2 + 1, mid + 1, rr);
}
void add (int x, int val, int v)
{
tree[v] += val;
if(l[v] == r[v])
return ;
int mid = l[v] + r[v] >> 1;
if(x <= mid)
{
add(x, val, v * 2);
}
else
{
add(x, val, v * 2 + 1);
}
}
int query (int v, int ll, int rr)
{
if(ll == l[v] && r[v] == rr)
{
return tree[v];
}
int mid = l[v] + r[v] >> 1;
int res = 0;
if(rr <= mid)
{
res += query(v * 2, ll, rr);
}
else
{
if(ll >= mid)
{
res += query(v * 2 + 1, ll, rr);
}
else
{
res += query(v * 2, ll, mid);
res += query(v * 2 + 1, mid + 1, rr);
}
}
return res;
}
int work (int val)
{
int l = 1;
int r = n;
int mid;
while(l != r)
{
mid = l + r >> 1;
if(query(1, 1, mid) >= val)
{
r = mid;
}
else
{
l = mid + 1;
}
// cout<<l<<r<<mid<<endl;
}
// cout<<endl;
return r;
}
int main()
{
scanf("%d", &n);
build(1, 1, n);
for(int i = 0; i < n; i ++)
{
scanf("%d", a + i);
b[i] = i + 1;
}
sort(b, b + n, cmp);
scanf("%d", &m);
for(int i = 0; i < m; i ++)
{
scanf("%d%d", &q[i].k, &q[i].p);
q[i].ind = i;
}
sort(q, q + m, cmp1);
for(int i = 0, j = 0; i < n; i ++)
{
add(b[i], 1, 1);
for(; j < m && q[j].k == i + 1; j ++)
{
ans[q[j].ind] = a[work(q[j].p) - 1];
}
}
for(int i = 0; i < m; i ++)
{
printf("%d\n", ans[i]);
}
}