p2034 選擇數字 - 單調佇列
gyro永不抽風
最後更新:2023年09月20日 - 21:09
許可協議:
給定一行n個非負整數a[1]..a[n]。現在你可以選擇其中若干個數,但不能有超過k個連續的數字被選擇。你的任務是使得選出的數字的和最大。
第一行兩個整數n,k
以下n行,每行乙個整數表示a[i]。
輸出乙個值表示答案。
輸入 #1複製
5 212345
輸出 #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]
$$
1234567
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 ...