描述
初始有一个空集,依次插入N个数Ai。有M次询问Bj,表示询问第Bj个数加入集合后的排名为j的数是多少
输入
第一行是两个整数N,M
接下来一行有N个整数,Ai
接下来一行有M个整数Bj,保证数据合法
输出
M行,回答每个询问
样例输入 [复制]
7 4
9 7 2 8 14 1 8
1 2 6 6
样例输出 [复制]
9
9
7
8
【说明】
第一次询问,当前几何{9},1th=9
第二次询问,当前集合{9,7}的第2=9
第三次询问,当前集合{9,7,2,8,14,1}的第3=7
第四次询问,当前几何{9,7,2,8,14,1}的第4=8
【数据规模】
40%的数据保证 n ≤ 1000
100%的数据保证1≤m≤n≤30000;0≤Ai<2^32
思路:
离线+权值线段树//要开long long。。。
#include<bits/stdc++.h>
#define sf scanf
#define lc (p<<1)
#define rc ((p<<1)|1)
#define int long long
//没开long long见祖宗。。。。
//真没开long long。。。。
//int <=2e31-1
using namespace std;
const int maxn=3e4+10;
int num[maxn],n,m,ans[maxn];
int sum[maxn<<2],hash[maxn<<1],tot=0;
vector <int> G[maxn];
void change(int p,int l,int r,int k){
if(l==r){
++sum[p];return;
}
int mid=(l+r)>>1;
if(k>mid) change(rc,mid+1,r,k);
else change(lc,l,mid,k);
sum[p]=sum[lc]+sum[rc];
}
int query(int p,int l,int r,int k){
if(l==r){
return hash[l];
}
int mid=(l+r)>>1;
if(k<=sum[lc])return query(lc,l,mid,k);
else return query(rc,mid+1,r,k-sum[lc]);
}
signed main(){
freopen("rollcall.in","r",stdin);
freopen("rollcall.out","w",stdout);
sf("%lld%lld",&n,&m);
for(int i=1;i<=n;++i){
sf("%lld",&num[i]);hash[i]=num[i];
}
for(int i=1;i<=m;++i){
int id;
sf("%lld",&id);
G[id].push_back(i);
}
sort(hash+1,hash+n+1);
tot=unique(hash+1,hash+n+1)-hash-1;
for(int i=1;i<=n;++i){
int id=lower_bound(hash+1,hash+tot+1,num[i])-hash;
change(1,1,tot,id);
for(int j=0;j<G[i].size();++j){
int k=G[i][j];
ans[k]=query(1,1,tot,k);
}
}
for(int i=1;i<=m;++i)printf("%lld\n",ans[i]);
return 0;
}