题解 P1801 【黑匣子_NOI导刊2010提高(06)】
数结渣表示不会平衡树,不知道怎么用堆处理。
然后用数组模拟双向链表弄了一下。
正难反易,把加节点过程当成删点就很容易了。
1.离线处理,先读入所有数据。
2.排序并维护每一个节点排序后的位置。
3.最开始指向最后一个访问节点,然后用双向链表删除操作删除节点,判断一下删除的节点和当前查找的(第i小)的节点的大小关系,如果删除节点小的话,将当前查找节点指针指向更大的下一个节点(有点抽象,看代码也可以),倒序保存答案。
const maxn=200010;
var i,j,k,l,m,n,now,link:longint;
del,dx,d:array[1..maxn]of longint;
a,next,pre:array[0..maxn]of longint;
v,sp:array[1..maxn]of int64;
procedure swap(i,j:longint);
var k:int64;
begin
k:=dx[i];dx[i]:=dx[j];dx[j]:=k;
k:=v[i];v[i]:=v[j];v[j]:=k;
end;
procedure qsort(l,r:longint);
var i,j,x:longint;
begin
i:=l;j:=r;x:=v[(l+r)shr 1];
repeat
while v[i]<x do inc(i);
while v[j]>x do dec(j);
if(i<=j)then
begin
swap(i,j);
inc(i);
dec(j);
end;
until(i>j);
if i<r then qsort(i,r);
if j>l then qsort(l,j);
end;
procedure init;
begin
readln(n,m);
for i:=1 to n do
begin
read(v[i]);
dx[i]:=i;
pre[i]:=i-1;
next[i]:=i+1;
end;
for i:=1 to m do read(del[i]);
qsort(1,n);
for i:=1 to n do d[dx[i]]:=i;
end;
procedure work;
var i,j,k,l,r,p:longint;
begin
now:=n;link:=m;
for i:=m downto 1 do
begin
j:=del[i];
for k:=now downto j+1 do
begin
l:=d[k];
next[pre[l]]:=next[l];
pre[next[l]]:=pre[l];
if(v[l]<v[link])and(l<link) then link:=next[link];
if(v[l]=v[link])and(l=link) then link:=next[link];
end;
now:=j;
sp[i]:=v[link];
link:=pre[link];
end;
for i:=1 to m do writeln(sp[i]);
end;
begin
init;
work;
end.