解法:
转换题意后,这题就是给定一个序列a,给出m个询问,问[0,k]的第pos小的数.
特殊就特殊在是从0开始的。
可以保存询问,我们让不同的询问ki从小到大排列,从小到大枚举k,将前ki个数存入树状数组,这时候可以通过二分答案来枚举答案mid,查询小于等于mid的数num,找出num=pos的最小的mid,就是第pos小的数了。
时间复杂度是O(nlog^2n)
应该能更快...还没去想
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
struct node
{
int x, y;
}a[maxn], b[maxn];
int c[maxn];
int bit[maxn];
int cmp(node a, node b)
{
if(a.x>b.x)return 1;
else if(a.x==b.x)
{
if(a.y<b.y)return 1;
else return 0;
}
else return 0;
}
int lowbit(int x)
{
return x&(-x);
}
int add(int x, int y)
{
for(int i=x; i<maxn; i+=lowbit(i))bit[i]+=y;
}
struct query{
int k, pos, id;
}q[maxn];
int cmp2(query a, query b)
{
return a.k<b.k;
}
int sum(int x)
{
int sum=0;
for(int i=x; i>0; i-=lowbit(i))sum+=bit[i];
// printf("sum\n");
return sum;
}
int ans[maxn];
int main()
{
int t, i, j, n, m;
scanf("%d", &n);
for(i=0; i<n; i++)
{
scanf("%d", &a[i].x);
c[i]=a[i].x;
a[i].y=i;
}
sort(a, a+n, cmp);
// for(i=0; i<n; i++)printf("%d\n", a[i].x);
scanf("%d", &m);
for(i=0; i<m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
q[i].k=x,q[i].pos=y, q[i].id=i;;
}
sort(q, q+m, cmp2);
int k=0;
for(i=0; i<m; i++)
{
while(k<q[i].k)
{
// printf("k%d\n", k);
add(a[k].y+1, 1);
// printf("k%d\n", k);
k++;
}
// printf("i%d\n", i);
int mid, l=1, r=maxn-2,mi=maxn;
for(j=0; j<100; j++)
{
mid=(l+r)>>1;
if(sum(mid+1)>=q[i].pos)
{
mi=min(mi, mid);
r=mid-1;
}
else l=mid+1;
}
ans[q[i].id]=mi;
}
for(i=0; i<m; i++)
{
printf("%d\n", c[ans[i]]);
}
return 0;
}