1. 程式人生 > 實用技巧 >洛谷P1714 切蛋糕(雙端佇列)

洛谷P1714 切蛋糕(雙端佇列)

題目地址:https://www.luogu.com.cn/problem/P1714

題意:給定n個數,從中選擇最多m個連續的數,使得這些數的和最大

輸入:第一行n,m。第二行,n個整數

輸出:輸出所選擇的數的和

題解:這道題第一感覺肯定是字首和,但是這裡有一個難點,就是最多是選擇m個連續的數,而不是一定是m個數,所以這裡面的複雜度就會有點高(如果暴力的話)。暴力就是找到第i個數的前面m個字首和的最小值,二者相減,然後去所有i的這二種結果的最大值,這裡如果暴力找到m個字首和的最小值,複雜度會非常高。所以我們可以通過雙端佇列來實現單調佇列的方法來求解最小值。

AC程式碼:

#include<iostream>
#include
<deque> using namespace std; const int N=500000+5; int sum[N];//字首和陣列 int main(){ deque<int>de; int n,m; cin>>n>>m; sum[0]=0; for(int i=1;i<=n;i++){ cin>>sum[i]; sum[i]+=sum[i-1]; } int ans=0; for(int i=1;i<=n;i++){
while(!de.empty()&&*de.begin()<i-m) de.pop_front();//如果佇列de中的最小值已經不再i的前m個範圍,那麼i和i以後的數都不會用到這個最小值了,所以出隊 while(!de.empty()&&sum[*(de.end()-1)]>=sum[i]) de.pop_back();//如果sum[i]小於等於佇列的尾部元素,那麼以後所有的i的前m個字首和的最小值都不可能是此時佇列的尾部元素 de.push_back(i); ans=max(ans,sum[i]-sum[*de.begin()]); } cout
<<ans; return 0; }

寫於2020/8/6 11:59