洛谷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

posted @ 2020-08-06 12:00  白菜茄子  阅读(266)  评论(0编辑  收藏  举报