題目描述 :
題目大意是,在一條直線上有n個點,我們要從中取出k對點(k*2<=n),點不能被重複取,每對點之間有乙個距離,求距離的最小和。
n不超過100000 k不超過 n div 2
容易證明,組成一對的兩個點一定 是相鄰的:
比如: a-------------------------b
c-----------------------d
如果ab一對,cd一對,那還不如ac一對,bd一對;
很明顯,dp是o(nk)的 :f[ i,k]:=min(f[ i-1,k],f[ i-2,k-1]+w[ i-1,i ])
f[i,k]表示掃到第i-1到第i 這兩個點,取了k對的最優值。
tle是明顯的,可以考慮效率更高的貪心。
因為只能選相鄰的點,我們不如用n-1 個距離代替n個點。
這樣,每次貪心的選取最小距離。
但這明顯是錯的,比如:a------------------------b--------------c------d----------e------------------------f
1000 10 1 10 100
如果我們直接貪心的選取了cd,那麼接下來就只能選ab或ef,這樣還不如選bc 和 ef
所以要對貪心進行修正,比如,我們在選了cd之後,刪除bc ,cd,de,然後構造 be=bc+de-cd=19,並新增進去:
a------------------------b------------------e------------------------f
1000 19 1000
這樣,當我們貪心選取be的時候,就等於把cd「還了回來」,並選取了bc和de兩段,等於說還是多選了一段
這樣,選一次就多選了一段,貪心選n次即可。
實現的時候,貪心取最小可以用堆(我的堆 寫醜了,其實用zkw線段樹更漂亮),刪除和新增需要有鍊錶輔助。
klog(n)的複雜度足夠了。
program lmd;
var pred,next,heap,link,dist:array[0..200000]of longint;
a:array[0..120000]of int64;
i,n,k,top,high:longint;
ans:int64;
procedure swap(x,y:longint);
var z:longint;
begin
link[heap[x]]:=y;
link[heap[y]]:=x;
z:=heap[x];heap[x]:=heap[y];heap[y]:=z;
end;
procedure up(k:longint);
begin
while (k<>1) and (a[heap[k shr 1]]>a[heap[k]]) do
begin
swap(k shr 1,k);
k:=k shr 1;
end;
end;
procedure down(k:longint);
var j:longint;
begin
while (heap[k shl 1]+heap[k shl 1+1]<>0) do
begin
j:=k shl 1;
if heap[j]=0 then j:=j+1;
if (a[heap[k shl 1+1]]0) then
j:=k shl 1+1;
if a[heap[j]]0)and(next[high]<>n+1) then
begin
del(pred[high]);
del(next[high]);
del(high);
a[high]:=a[pred[high]]+a[next[high]]-a[high];
a[pred[high]]:=maxlongint shr 2;
a[next[high]]:=maxlongint shr 2;
add(high);
pred[high]:=pred[pred[high]];
next[pred[high]]:=high;
next[high]:=next[next[high]];
pred[next[high]]:=high;
endelse
begin
del(high);
if pred[high]=0 then
begin
del(next[high]);
pred[next[next[high]]]:=0;
end;
if next[high]=n+1 then
begin
del(pred[high]);
next[pred[pred[high]]]:=n+1;
end;
end;
end;
write(ans);
close(input);close(output);
end.
題解 APIO2007 風鈴
你需要選乙個滿足下面兩個條件的風鈴 1 所有的玩具都在同一層 也就是說,每個玩具到天花板之間的杆的個數是一樣的 或至多相差一層。2 對於兩個相差一層的玩具,左邊的玩具比右邊的玩具要更靠下一點。風鈴可以按照下面的規則重新排列 任選一根杆,將杆兩頭的線 交換 也就是解開一根杆左右兩頭的線,然後將它們綁到...
題解 APIO2007 動物園
傳送門 對於這個題目很明顯的就是狀壓dp,不過,作為乙個不會狀壓dp的蒟蒻,考場讓只能根據大佬們的之前聊天和對狀壓dp的印象來瞎搞 狀態是這樣設計的 f i,j 表示轉移到從第i個位置出發的j表示五個的動物的狀態能使多少個小朋友滿意 s i,j 表示從i出發的5個位置中表示j的狀態使多少個小朋友滿意...
題解 APIO2007動物園
首先一眼感受到這題特別的性質 5個?這麼小的,感覺就像是狀壓。腦補了一下,如果沒有環的話應該很好做吧 有環怎麼辦?5真的很小的,隨便亂搞肯定也可以。那就放在外面暴力列舉吧。然後正解就出來了。然而這題題面真的有毒吧。說好的不能全部選走?我還多加了乙個維度,結果資料裡面允許全部取走 然後對於 5的點單獨...