题目大意:
给定一个长度为n的序列a,试求出对于序列a的每一个前缀的终极数x,使得
最小,试求出终极数t(如若有多个终极数t,只需输出最小的那个)
题解:
虽然看似很迷,其实就是每次插入后的中位数中排序后的中位数:
我们维护两个堆来处理,一个大根堆,一个小根堆,当前每次加入一个数,必须保证
小根堆的个数大于等于大根堆的个数,可以理解为——第一次加入数的时候肯定是放
到最小堆。
其次,我们还需保证小根堆里的每个值必须大于等于大根堆当中的最大值,这样就可以使得每次小根堆的堆顶必定是当前的中位数。
然后每次插入任意一个堆中的数,就要维护,然后判断2个堆的堆顶
堆顶/小 < 堆顶/大 这时候很明显我们需要替换,然后替换后分别维护一下,维护后继续判断,直到满足小根堆根大根堆的定义以及满足小根堆的每个值都大于等于大根堆得最大值。
最后将记录下来的中位数排序输出最终的中位数,即终极数。
var
smbi:array [1..2,0..1000001] of longint;
b:Array [0..1000001] of longint;
n,i,j,k1,k2,d1,d2,x:longint;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
if l>=r then exit;
i:=l; j:=r;
mid:=b[(l+r) div 2];
repeat
while b[i]<mid do inc(i);
while b[j]>mid do dec(j);
if i<=j then
begin
b[0]:=b[i];
b[i]:=b[j];
b[j]:=b[0];
inc(i); dec(j);
end;
until i>j;
qsort(i,r);
qsort(l,j);
end;
procedure down(x,y:longint);
var
t:longint;
begin
if y*2>smbi[x,0] then exit;
if x=1 then
repeat
y:=y*2;
if y<smbi[x,0] then
if smbi[x,y]<smbi[x,y+1] then inc(y);
if smbi[x,y div 2]<smbi[x,y]
then begin
t:=smbi[x,y];
smbi[x,y]:=smbi[x,y div 2];
smbi[x,y div 2]:=t;
end
else break;
until y*2>smbi[x,0];
if x=2 then
repeat
y:=y*2;
if y<smbi[x,0] then
if smbi[x,y]>smbi[x,y+1] then inc(y);
if smbi[x,y div 2]>smbi[x,y]
then begin
t:=smbi[x,y];
smbi[x,y]:=smbi[x,y div 2];
smbi[x,y div 2]:=t;
end
until y*2>smbi[x,0];
end;
procedure up(x,y:longint);
var
k,t:longint;
begin
if y=1 then exit;
if x=1 then
repeat
if smbi[x,y]>smbi[x,y div 2]
then begin
t:=smbi[x,y];
smbi[x,y]:=smbi[x,y div 2];
smbi[x,y div 2]:=t;
end
else break;
y:=y div 2;
until y=1;
if x=2 then
repeat
if smbi[x,y]<smbi[x,y div 2]
then begin
t:=smbi[x,y];
smbi[x,y]:=smbi[x,y div 2];
smbi[x,y div 2]:=t;
end
else break;
y:=y div 2;
until y=1;
end;
procedure check;
var
i:longint;
begin
i:=smbi[2,1];
smbi[2,1]:=smbi[1,1];
smbi[1,1]:=i;
end;
begin
assign(input,'c.in');reset(input);
assign(output,'c.out'); rewrite(output);
readln(n);
smbi[1,0]:=0; smbi[2,0]:=0;
k1:=1; k2:=1; d1:=1; d2:=1;
for i:=1 to n do
begin
read(x);
if i mod 2<>0 then begin
if smbi[2,0]<k1
then smbi[2,0]:=smbi[2,0]+1
else begin smbi[2,0]:=smbi[2,0]+1; d1:=d1*2; k1:=k1+d1 end;
smbi[2,smbi[2,0]]:=x;
up(2,smbi[2,0]);
end
else begin
if smbi[1,0]<k2
then smbi[1,0]:=smbi[1,0]+1
else begin smbi[1,0]:=smbi[1,0]+1; d2:=d2*2; k2:=k2+d2 end;
smbi[1,smbi[1,0]]:=x;
up(1,smbi[1,0]);
end;
while smbi[2,1]<smbi[1,1] do
begin
check;
down(2,1);
down(1,1);
end;
b[i]:=smbi[2,1];
end;
qsort(1,n);
writeln(b[n div 2]);
close(input); close(output);
end.