题目地址: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