[Description]
我们的黑盒子代表一个原始数据库,它可以储存一个整数数组,并且有一个特殊的变量 i,
一开始黑盒子是空的而且 i = 0。这个黑盒子会给出一系列的指令,有如下两种:
ADD (x) 把 x 放入黑盒子中
GET 把 i 增加 1, 并且找出整个黑盒子中第 i 小的数 (第 i 小的数是把黑盒
子中全部的数按照不降排序后的第 i 个数) 。
[Input]
第一行两个整数 M 和 N,分别表示黑盒子里将要加入的元素个数和 GET 的操作个数
第二行 M 个整数 A(i),分别表示黑盒子将要加入的 M 个元素
第三行 N 个整数 u(i),分别表示在加入了 A(1) ~ A(u(i)) 之间的元素后,要执行一次 GET
并且保证 u(i) 按照不降的顺序给出
[Output]
输出 N 行,每行一个整数,对应每一次执行 GET 后的结果
[Sample Input]
7 4
3 1 -4 2 8 -1000 2
1 2 6 6
[Sample Output]
3
3
1
2
[Hint]
N, M <= 30000, |A(i)| <= 2 000 000 000, 1 <= u(i) <= N
样例解释:
1 ADD(3) i=0 3
2 GET i=1 3 3
3 ADD(1) i=1 1, 3
4 GET i=2 1, 3 3
5 ADD(-4) i=2 -4, 1, 3
6 ADD(2) i=2 -4, 1, 2, 3
7 ADD(8) i=2 -4, 1, 2, 3, 8
8 ADD(-1000) i=2 -1000, -4, 1, 2, 3, 8
9 GET i=3 -1000, -4, 1, 2, 3, 8 1
10 GET i=4 -1000, -4, 1, 2, 3, 8 2
11 ADD(2) i=4 -1000, -4, 1, 2, 2, 3, 8
标程是开两个优先队列,水过
#include <cstdio>
#include <queue>
#include <vector>
using std::vector;
using std::priority_queue;
using std::greater;
const int N = 30000 + 10;
int n, m, a[N];
priority_queue<int> Qmax;
priority_queue<int, vector<int>, greater<int> > Qmin;
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
int last = 0;
int i = 0;
while(m--)
{
i++;
int q; scanf("%d", &q);
for(int j = last+1; j <= q; j++) Qmin.push(a[j]);
while(Qmax.size() < i)
{
Qmax.push(Qmin.top());
Qmin.pop();
}
while(Qmin.size() && Qmax.top() > Qmin.top())
{
int x1 = Qmax.top(); Qmax.pop();
int x2 = Qmin.top(); Qmin.pop();
Qmin.push(x1); Qmax.push(x2);
}
printf("%d\n", Qmax.top());
last = q;
}
return 0;
}
我继续NC地写了个线段树
//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/////////////////////////////////////////////////
#define for0(i,j) for(int i=0;i<j;i++)
#define for1(i,j) for(int i=1;i<=j;i++)
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
#define inf 0x7fffffff
/////////////////////////////////////////////////
//离线+线段树
int m,n;
int A[30010];
int B[30010];
int u[30010];
int val[70000];
int sz[70000];
int mmax[70000];
int mmin[70000];
int ans[30010];
/////////////////////////////////////////////////
void pushup(int id)
{
int lc=id<<1,rc=lc|1;
sz[id]=sz[lc]+sz[rc];
//test
/*mmax[id]=max(mmax[id<<1],mmax[id<<1|1]);
mmin[id]=min(mmin[id<<1],mmin[id<<1|1]);*/
if(mmax[lc]==inf && mmax[rc]==inf) mmax[id]=inf;
else if(mmax[lc]==inf) mmax[id]=mmax[rc];
else if(mmax[rc]==inf) mmax[id]=mmax[lc];
else mmax[id]=max(mmax[lc],mmax[rc]);
mmin[id]=min(mmin[lc],mmin[rc]);
}
void build(int id,int l,int r)
{
val[id]=inf;
sz[id]=r-l+1;
if(l==r)
{
mmax[id]=mmin[id]=val[id]=B[l];
return;
}
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}
void del(int id,int x,int L,int R)
{
if(L==R)
{
mmax[id]=mmin[id]=val[id]=inf;
sz[id]--;
return;
}
int mid=(L+R)>>1;
if(mmax[id<<1] !=inf && mmax[id<<1]>=x) del(id<<1,x,L,mid);
else del(id<<1|1,x,mid+1,R);
pushup(id);
}
int query(int id,int x,int L,int R)
{
if(L==R)
{
return val[id];
}
//test
int mid=(L+R)>>1;
if(sz[id<<1]>=x) return query(id<<1,x,L,mid);
else return query(id<<1|1,x-sz[id<<1],mid+1,R);
}
/////////////////////////////////////////////////
void input()
{
scanf("%d%d",&n,&m);
rep(i,1,n) scanf("%d",&A[i]);
rep(i,1,m) scanf("%d",&u[i]);
memcpy(B,A,sizeof(A));
}
void solve()
{
///////////////////init///////////////////
int size=n;
sort(&B[1],&B[n+1]);
build(1,1,n);
////////////////calculate////////////////
for(int i=m;i>=1;i--)
{
while(size>u[i])
{
del(1,A[size],1,n);//删除数值
size--;
}
ans[i]=query(1,i,1,n);//第i大
}
/////////////////output/////////////////
rep(i,1,m) printf("%d\n",ans[i]);
}
/////////////////////////////////////////////////
int main()
{
#ifndef _TEST
freopen("D.in","r",stdin); freopen("D.out","w",stdout);
#endif
input();
solve();
#ifdef _TEST
for(;;);
#endif
return 0;
}