給定一行n個非負整數a[1]..a[n]。現在你可以選擇其中若干個數,但不能有超過k個連續的數字被選擇。你的任務是使得選出的數字的和最大。
輸入格式
第一行兩個整數n,k
以下n行,每行乙個整數表示a[i]。
輸出乙個值表示答案。
5 2123
45對於20%的資料,n <= 10
對於另外20%的資料, k = 1
對於60%的資料,n <= 1000
對於100%的資料,1 <= n <= 100000,1 <= k <= n,0 <= 數字大小 <= 1,000,000,000
時間限制500ms
一般正常求序列幾段和都要求字首和,f的第一維都是前i項的最優值
那我們直接開始吧,
f[i]=max(f[j])+a[i] ( i-k<=j然鵝叫上去可能只對兩個點(可能連樣例都不過),原因是方程都錯了,少了一維,i不一定選取就是最佳選擇,如1 8 4 2 999 k=2,顯然不選4要更優, 所以正確的轉移方程:
//0表示不選第i個數,1表示選第i個數
f[0][i]=max(f[0][i-1],f[1][i-1]);
f[1][i]=max(f[0][j]-sum[j])+sum[i];
親測o(n*n)
+快讀能壓線過
所以考慮優化
我們用單調佇列維護f[0][j]-sum[j]的最優值,因為它完全符合單調性,維護就完事
/*#!/bin/sh
dir=$gedit_current_document_dir
name=$gedit_current_document_name
pre=$
g++ -o2 $dir/$name -o $pre -g -wall -std=c++11
if test $? -eq 0; then
gnome-terminal -x bash -c "time $dir/$pre;echo;read;"
fi*/
#include#include#include#include#includeusing namespace std;
const int maxn=1e6+5,inf=0x3f3f3f3f;
inline int read();
while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
return s*w;
}int n,d,a[maxn],head=1,tail;
long long sum[maxn],f[2][maxn],q[maxn];//每個數有1e9誒
int main()
cout<}
P2034 選擇數字 單調佇列
p2034 選擇數字 單調佇列 gyro永不抽風 最後更新 2020年09月20日 21 09 許可協議 給定一行n個非負整數a 1 a n 現在你可以選擇其中若干個數,但不能有超過k個連續的數字被選擇。你的任務是使得選出的數字的和最大。第一行兩個整數n,k 以下n行,每行乙個整數表示a i 輸出乙...
單調佇列優化
單調佇列是一種嚴格單調的佇列,可以單調遞增,也可以單調遞減。隊首位置儲存的是最優解,第二個位置儲存的是次優解。單調佇列可以有兩個操作 1 插入乙個新的元素,該元素從隊尾開始向隊首進行搜尋,找到合適的位置插入之,如果該位置原本有元素,則替換它。2 在過程中從隊首刪除不符合當前要求的元素。單調佇列實現起...
單調佇列 優化DP
佇列元素保持單調遞增 減 而保持的方式就是通過插隊,把隊尾破壞了單調性的數全部擠掉,從而使佇列元素保持單調。單調佇列的作用 優化dp。許多單調佇列優化的dp可以使複雜度直接降維,下面就以最簡單的一道題為例 在某兩座城市之間有 n 個烽火台,每個烽火台發出訊號都有一定代價。為了使情報準確地傳遞,在連續...