首先,把數都弄成字首和sum[i],節約時間;
列舉右端點i,當i固定的時候,問題就變成了,尋找乙個左端點j,j在區間
[i-m,i-1]內,並且sum[j]最小;
使用乙個單調佇列來完成此題,我們從左往右掃一遍右端點,對每個i:
1.判斷當前隊頭的數與i的距離是否大於m,大於就把隊頭乾掉
2.此時隊頭就是右端點為i時的最佳答案(因為,不是最佳的答案在每次第三步更新sum[i]進隊的時候都被乾掉了)
3.不斷刪除隊尾直到隊尾的s值小於s[i](因為如果乙個s值比s[i]大,他的位置又比i靠左,那麼他是沒有存在意義的),將s[i]入隊;
兩種寫法:
1.陣列模擬
#include
#include
#include
using namespace std;
long long sum[300005];
int main()
long long ans=1
<<31;//q儲存的是數列中數的位置
l=r=1;int
q[300005];q[1]=0;//第乙個入列的一定是0,因為字首和存在s[i]-s[0]的情況,代表的是第1到個數
for(i=1;i<=n;i++)
cout0;}
2.使用stl雙端佇列
#include
#include
#include
using
namespace
std;
deque
int,int> >que;
int sum[300005];
int main()
que.push_front(pair(sum[0],0));
int ans=1
<<31;
for(i=1;i<=n;i++)
cout
0;}
tyvj 1305(單調佇列)
傳送門 題意 輸入乙個長度為n的整數序列,從中找出一段不超過m的連續子串行,使得整個序列的和最大。題解 維護乙個關於字首和的單調遞增的佇列,每次用隊首更新答案,將元素插入隊尾。p.s.我是乙隻單調佇列都做不來的菜雞。include include include include using name...
tyvj1305 最大子序和(單調佇列
時間限制 記憶體限制 評測方式 題目 1000ms 131072kib 標準比較器 local 輸入乙個長度為n的整數序列,從中找出一段不超過m的連續子串行,使得整個序列的和最大。例如 1,3,5,1,2,3 當m 4時,s 5 1 2 3 7 當m 2或m 3時,s 5 1 6 第一行兩個數n,m...
tyvj 1305 最大子序和 dp 單調佇列
時間限制 記憶體限制 評測方式 題目 1000ms 131072kib 標準比較器 local 輸入乙個長度為n的整數序列,從中找出一段不超過m的連續子串行,使得整個序列的和最大。例如 1,3,5,1,2,3 當m 4時,s 5 1 2 3 7 當m 2或m 3時,s 5 1 6 第一行兩個數n,m...