洛谷 P3620 資料備份

2022-05-10 05:49:37 字數 1523 閱讀 3821

首先我們發現乙個顯然的貪心策略,連線相鄰兩個寫字樓總是更優.

所以本題就變成了數軸上一堆點,要選 k 個彼此不相鄰的區間,使得區間長度最小

對於 10000 的資料來說,我們可以用 dp 解決,

f[i][j]表示考慮前i個點,已經形成j對點的最小距離,num[i]表示第i個點的座標。

如果這個點不與其他點組成一對,那麼f[i][j]=f[i-1][j]。

否則這個點只能和前面的點組成一對,f[i][j]=f[i-2][j-1]+num[i]-num[i-1]。

f[i][j]=min(f[i-1][j],f[i-2][j-1]+num[i]-num[i-1]);

時間複雜度o(nk) ,可以滾動陣列優化過。

對於全部資料來說,我們有一種非常奇特的貪心

這裡有乙個非常精妙的轉化。假設在原先的n個點上有abcde5個相鄰點(a假設bc是最小的那個,我們貪心把bc選出來,然後加入答案以後刪除。之後我們同時把與bc相鄰的ab,cd取出來。把這三個值全都刪除後合成乙個新的值,這個值=ab+cd-bc。那麼如果我們再次通過貪心原則把這個ab+cd-bc選出來加入答案,那麼其中的-bc會和一開始選擇的bc抵消,相當於我們這兩次選擇了ab+cd,也就是與bc相鄰的兩段。每一次選擇會把已選擇的段的數量+1,所以選擇k次以後的ans就是最優解, 這類似於網路流的退流操作

我們需要用鍊錶維護每個元素的前驅後繼, 並且需要維護乙個可以刪除任意乙個元素(不只是根元素)的堆,

這裡有兩種操作, 如果維護的值比較小,可以維護乙個 bool 陣列來標記被刪除的元素, 如果被維護的元素很大, 我們需要維護乙個刪除堆, 每次詢問的時候,比較刪除堆與

原堆的堆頂, 如果一樣就 pop

#include #include #include #include #include #include #define ll long long

using namespace std;

const int maxn = 100005;

int init()

while(c >= '0' && c <= '9')

return fh * rv;

}int n, k, loc[maxn], num[maxn], pre[maxn], nxt[maxn];

struct node

};priority_queuehea;

bool del[maxn];

ll ans;

int main() );

} }for(int i = 1; i <= n; i++)

nxt[0] = 1; nxt[n] = 0;

num[0] = num[n] = 0x3f3f3f3f;

for(int i = 1; i <= k; i++) );

pre[x] = pre[l]; nxt[x] = nxt[r];

pre[nxt[r]] = x; nxt[pre[l]] = x;

} cout << ans << endl;

return 0;

}

洛谷P5049 洛谷P5022 題解 旅行

原題 資料加強版 加強版 參考你谷題解 終於調過了 又是一如既往的申必錯誤 noi plus石錘了 原題的資料允許我們 o n 2 暴力斷邊,但是加強版的資料達到了 n log n 級別,我們必須在斷邊這一環節尋求更好的解法。考慮我們進入環後在何處回溯 根據繼續走環走到的點分類 設當前已經從 b 走...

洛谷 P2097 資料分發1

有一些電腦,一部分電腦有雙向資料線連線。如果乙個電腦得到資料,它可以傳送到的電腦都可以得到資料。現在,你有這個資料,問你至少將其輸入幾台電腦,才能使所有電腦得到資料。輸入格式 第一行兩個數n,m。n是點數,m是邊數。接下來m行,每行2個整數p,q表示p到q有一條雙向資料線。輸出格式 乙個整數,表示至...

洛谷練習P2279 P1346

2020年,人類在火星上建立了乙個龐大的基地群,總共有n個基地。起初為了節約材料,人類只修建了n 1條道路來連線這些基地,並且每兩個基地都能夠通過道路到達,所以所有的基地形成了乙個巨大的樹狀結構。如果基地a到基地b至少要經過d條道路的話,我們稱基地a到基地b的距離為d。由於火星上非常乾燥,經常引發火...