jzoj P2152 2017 7 7普及 終極數

2021-08-03 13:52:14 字數 3746 閱讀 1628

題目大意:

給定乙個長度為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]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 y0] then

if smbi[x,y]1] then inc(y);

if 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;

endelse

break;

until y*2>smbi[x,0];

if x=2

then

repeat

y:=y*2;

if y0] 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;

enduntil 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;

endelse

break;

y:=y div

2; until y=1;

if x=2

then

repeat

if 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;

endelse

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]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]);

endelse

begin

if smbi[1,0]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]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.

jzoj P1330 迎接儀式

給出乙個不和諧的佇列,用 j 替代 教 z 替代 主 而乙個 j 與 z 組成的序列則可以描述當前的佇列。為了讓教主看得盡量舒服,你必須調整佇列,使得 jz 子串盡量多。每次調整你可以交換任意位置上的兩個人,也就是序列中任意位置上的兩個字母。而因為教主馬上就來了,時間僅夠最多作k次調整 當然可以調整...

jzoj P1331 超級教主

lhx教主很能跳,跳需要消耗能量,每跳1公尺就會消耗1點能量。教主為了收集能量,來到了乙個神秘的地方,教主的正上方每100公尺處就有乙個能量球 也就是這些能量球位於海拔100,200,300 公尺處 每個能量球所能提供的能量是不同的,一共有n個能量球 也就是最後乙個能量球在n 100公尺處 教主為了...

jzoj P3796 議案決定

國王手下有m個大臣,他們有一天對國王要處理的n件事務進行投票。每個大臣可以對兩件事務贊成或反對,格式如下 x c x y c y表示這個大臣對事務x的態度為c x,對事務y的態度為c y。如果國王的決定和某個大臣的兩個意見都不同,那麼這個大臣就會離開國王。小c認為不能讓任何乙個大臣離開國王,否則國王...