長度不超過m的最大連續子串行(dp 單調佇列)

2021-08-01 01:11:06 字數 1095 閱讀 5654

給你n個數,然後讓你求最大連續子串行的和,限制條件是連續子串行的長度不超過m。

n,m  <= 100000;

就是讓你找到乙個長度不超過m的區間,區間和最大。

普通的dp轉移方程就是 dp[i] = sum[i] - min(sum[j] | i- m <= j <= i) 

但是這樣的複雜度最壞會達到n^2,所以得優化,就用到了單調佇列。

針對這題來說一下什麼是單調佇列,這題我們需要存下距離不超過m,且最小的字首和的下標。

如果來了乙個字首,肯定下標是比在佇列裡的是靠後的,如果它的值還比佇列裡的小,那麼佇列裡的元素就沒有必要存在了,就把它們踢出去。

舉個例子,假設右邊是佇列的首,左邊是佇列的尾,現在佇列裡的元素的值(注意這裡不是下標,下標靠近隊首的較小)為 ,現在又來了乙個值為1的數,那麼它要和隊尾的元素對應的值進行比較,發現比5,4都小,所以5,4都被彈出佇列,比到-2的時候沒有-2小,所以插入佇列。

這樣的話最小值就是隊首的元素,當然在用隊首元素的時候還要在看一下當前的隊首元素還符不符合限制條件,如果不符合就彈出。

因為每個元素最多隻會進一次佇列,出一次佇列,所以複雜度就是o(n)。

這裡用了鍊錶來模擬佇列,就可以方便的對隊首隊尾元素進行操作。

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

using namespace std;

ll sum[1000010];

listq;

int main(void)

ll maxn = 0;

while(!q.empty())

q.pop_back();

q.push_front(0);

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

q.push_front(i);

while(!q.empty() && i - q.back() > m)//如果長度已經超過m

maxn = max(maxn,sum[i] - sum[q.back()]);

}cout << maxn << endl;

}return 0;

}

最大連續子串行之和,最大連續子串行乘積

最大連續子串行之和問題描述為 陣列中里有正數也有負數,連續的乙個或多個整數組成乙個子陣列,每個子陣列都有乙個和,求所有子陣列的和的最大值。分析,對陣列a進行一遍掃瞄,sum i 為前i個元素中,包含第i個元素且和最大的連續子陣列,maxsum儲存當前子陣列中最大和,對於a i 1 來說,sum i ...

最大連續子串行

e 最大連續子串行 description 給定k個整數的序列,其任意連續子串行可表示為,其中 1 i j k。最大連續子串行是所有連續子串行中元素和最大的乙個,例如給定序列,其最大連續子串行為,最大和 為20。在今年的資料結構考卷中,要求編寫程式得到最大和,現在增加乙個要求,即還需要輸出該 子串行...

最大連續子串行

問題描述 已知序列 a 0 a 1 a 2 a n 要求出連續子串行a i a i 1 a i 2 a j 0 i j n 使其和最大。演算法1 暴力列舉,簡單,但是效率不高。由於有三層迴圈,故時間複雜度為o n 3 max a 0 max不能為0 for i 0 i n i if sum max ...