P2034 選擇數字 單調佇列

2022-07-16 12:00:12 字數 1520 閱讀 5365

p2034 選擇數字 - 單調佇列

gyro永不抽風

最後更新:2023年09月20日 - 21:09

許可協議:

給定一行n個非負整數a[1]..a[n]。現在你可以選擇其中若干個數,但不能有超過k個連續的數字被選擇。你的任務是使得選出的數字的和最大。

第一行兩個整數n,k

以下n行,每行乙個整數表示a[i]。

輸出乙個值表示答案。

輸入 #1複製

5 212

345

輸出 #1複製

12

對於20%的資料,n <= 10

對於另外20%的資料, k = 1

對於60%的資料,n <= 1000

對於100%的資料,1 <= n <= 100000,1 <= k <= n,0 <= 數字大小 <= 1,000,000,000

時間限制500ms

我們要選出和最大的一堆數,但是這非常難,所以我們可以考慮怎麼做才能刪除最少的數。設$f[i]$表示刪除第$i$個數的最小和,那麼$f[i]$可以由前$k+1$個$f$轉移而來(因為是不超過$k$個),即以下轉移方程給出:

$$ f[i] = a[i] + \min_ f[j]

$$觀察後半段,其實就是個單調佇列,直接維護就行了。最後的答案:

$$ \text = \text[n] - \min_ f[i]

$$

123

4567

891011

1213

1415

1617

1819

2021

2223

2425

2627

2829

30

#include

#define int long long

using

namespace

std;

const

int maxn = 100005;

int n, k, f[maxn], a[maxn];

struct

node q[maxn];

signed

main();

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

while (head < tail && i - q[head].pos + 1 > k + 1) head ++;

}// for (int i = 0; i <= n; i ++) cout << f[i] << " ";

// cout << endl;

int ans = 8e18;

for (int i = n - k; i <= n; i ++) ans = min(ans, f[i]);

cout

<< sum - ans << endl;

return0;}

十年oi一場空,不開longlong見祖宗。

洛谷P2034 選擇數字

題目描述 給定一行n個非負整數a 1 a n 現在你可以選擇其中若干個數,但不能有超過k個連續的數字被選擇。你的任務是使得選出的數字的和最大。輸入格式 第一行兩個整數n,k 以下n行,每行乙個整數表示a i 輸出格式 輸出乙個值表示答案。乙個小dp 我們設f i 為不選i時候的最優值 然後我寫了個6...

單調佇列優化DP P2034 選擇數字

給定一行n個非負整數a 1 a n 現在你可以選擇其中若干個數,但不能有超過k個連續的數字被選擇。你的任務是使得選出的數字的和最大。輸入格式 第一行兩個整數n,k 以下n行,每行乙個整數表示a i 輸出乙個值表示答案。5 2123 45對於20 的資料,n 10 對於另外20 的資料,k 1 對於6...

luogu P2034 選擇數字

題面傳送門 對於這道題,簡單粗暴的dpdp dp是不難想的,dpdp dp方程式為fi max fj 1 s j 1i as f i max f sum ia s fi ma x fj 1 s j 1i as 其中max i k 0 j i 1max i k,0 leq j leq i 1 max ...