题目描述:
我们使用黑匣子的一个简单模型。它能存放一个整数序列和一个特别的变量i。在初始时刻,黑匣子为空且i等于0。这个黑匣子能执行一系列的命令。有两类命令:
ADD(x):把元素x放入黑匣子;
GET:把i加1的同时,输出黑匣子内所有整数中第i小的数。牢记第i小的数是当黑匣子中的元素已非降序排序后位于第i位的元素。
现需要一个有效的算法处理给定的一系列命令。ADD和GET命令的总数至多个有30000个。定义ADD命令的个数为M个,GET命令的个数为N个。
1.A(1),A(2),…A(M):一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数。
2.u(1),u(2),…u(N):表示第u(j)个元素被放进了Blaek Box里后就出现一个GET命令。例如上面的例子中u=(l,2,6,6)。输入数据不用判错。
输入格式:
第一行,两个整数,M,N。
第二行,M个整数,表示A(l)……A(M)。
第三行,N个整数,表示u(l)…u(N)。
输出格式:
输出Black Box根据命令串所得出的输出串,一个数字一行。
题解:第一种方法就是用平衡树硬解,很管用。
第二种方法:开左右两个堆,左堆为大根堆,右堆为小根堆(方便转移),一个变量KAF用于记录当前答案,维护这两个堆:1.左堆的所有元素都小于等于KAF; 2.右堆所有元素都大于等于KAF ; 3.左堆的元素数量维持在i-1。
#第一种方法
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<time.h>
using namespace std;
int l[300004],r[300004],s[300004],w[300004],rnd[300004],sz=0;
int neta=0,n,m,root=0;
int a[300004],u[300004];
void update(int x){s[x]=s[l[x]]+s[r[x]]+1;}
void lturn(int &x){
int t=r[x];
r[x]=l[t];
l[t]=x;
s[t]=s[x];
update(x);
x=t;
}
void rturn(int &x){
int t=l[x];
l[x]=r[t];
r[t]=x;
s[t]=s[x];
update(x);
x=t;
}
void add(int &k,int x){
if(k==0){
k=++sz;w[k]=x;
rnd[k]=rand();s[k]=1;return;
}
s[k]++;
if(x<w[k]){
add(l[k],x);
if(rnd[k]>rnd[l[k]])rturn(k);
}
else {
add(r[k],x);
if(rnd[k]>rnd[r[k]])lturn(k);
}
}
int find(int k,int x){
if(x==0)return -1;
if(x<=s[l[k]])return find(l[k],x);
else if(x>s[l[k]]+1)return find(r[k],x-s[l[k]]-1);
else return w[k];
}
int main(){
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++)scanf("%d",&u[i]);
int p=1;
for(int i=1;i<=m;i++){
add(root,a[i]);
while(i==u[p]){
printf("%d\n",find(root,p));
++p;
}
}
return 0;
}
#第二种方法
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<vector>
using namespace std;
priority_queue<int,vector<int>,less<int> >q1;
priority_queue<int,vector<int>,greater<int> >q2;
int n,m,a[200004],KAF,ok=-1,ep=0;
int g[200004];
void repute(){
if(q2.empty()){
ok=-1;
q1.push(KAF);
return;
}
while(q1.size()<ep){
q1.push(KAF);KAF=q2.top();q2.pop();
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
g[x]++;
}
for(int i=1;i<=n;i++){
if(ok == -1){
ok = 1;
KAF = a[i];
}
else{
if(a[i]<KAF){
q2.push(KAF);
KAF = a[i];
}
else q2.push(a[i]);
}
if(!q1.empty()&&a[i]<q1.top()){
int x=q1.top();
q1.pop();
KAF=x;
q1.push(a[i]);
}
while(g[i]--){
printf("%d\n",KAF);
++ep;
repute();
}
}
return 0;
}