loj 最大連續和

2022-07-12 00:27:11 字數 1251 閱讀 9358

loj

給你 n 個數的序列,找出一段連續的長度不超過 m 的非空子序列,使得這個序列的和最大。

\(1 \leq n , m \leq 2e5\)

有乙個非常顯然的 dp,\(f_i = \max \big\^i a_j \big| k \in [1,m]\big\}\)

然而這樣做是 \(\operatorname(nm)\) 的,並不優秀。

我們令 \(s_i = \sum_^i a_j\),則:

\[\begin

f_i&=\max \big\^i a_j \big| k \in [1,m] \big\} \\

f_i&=\max \big\ \big| k \in [1, m]\big\}\\

f_i&=s_i - \min\big\ \big| k\in[1,m]\big\}

\end

\]考慮用佇列來維護決策值 \(s_\) ,每次只需要在隊首刪除 \(s_\),在隊尾加入 \(s_\),但是取最小值的操作還是需要 \(\operatorname(m)\) 實現。

考慮在新增 \(s_\) 的時候,設現在隊尾元素為 \(s_k\) ,由於 \(k < i-1\),所以 \(s_k\) 必然比 \(s_\) 先出隊。若此時 \(s_ \leq s_k\),則 \(s_k\) 這個決策就永遠不會再以後用到,可以將 \(s_k\) 從隊尾刪除,此時的隊尾就形成了乙個類似棧的乙個東西。

同理,若隊尾的兩個元素 \(s_i\) 和 \(s_j\) ,若 \(i < j\)且 \(s_i \geq s_j\),則我們可以刪掉 \(s_i\),因為 \(s_i\) 永遠都不會用到了,此時的佇列中的元素構成了乙個單調遞增的序列,即 \(s_1 < s_2 < \dots < s_k\)。

維護的時候只需要這麼做就行了。

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

#define n 200010

#define m 1010

using namespace std;

const int mod = 1e9+7;

const int inf = 0x3f3f3f3f;

int n, m, head, tail;

int s[n], a[n], q[n], f[n], num[n];

int read()

int main()

cout << ans;

}

最大連續和

這個問題對我來說還挺難的,當初做dp時水過去了,但沒徹底理解,這次打算好好分析一下,爭取徹底搞懂。首先,像 1 1 2 2 3 3 4 4 5 5這樣的數列,想要找連續最大和,可以有很多種方法,從最慢的列舉o n 3 到最快的動態規劃o n 毫無疑問,我們要選擇複雜度低的演算法。所以我這裡就只分析兩...

最大連續和

求陣列中數的最大連續和,如 1,1,1,1,1 最大連續和為3 一 動態規劃 當我們從頭到尾遍歷這個陣列的時候,對於陣列裡的乙個整數,它有幾種選擇呢?它只有兩種選擇 1 加入之前的subarray 2.自己另起乙個subarray。那什麼時候會出現這兩種情況呢?設狀態為f j 表示以s j 結尾的最...

最大連續和

給出乙個長度為n的序列a1,a2,an,求最大連續和 使用列舉 時間複雜度o n 3 best a 1 初始最大值 for int i 1 i n i 設si a1 a2 ai,則ai ai 1 aj sj si 1 連續子串行的和等於兩個字首之差 時間複雜度o n 2 s 0 0 for int ...