单调队列
来源:互联网 发布:淘宝新店怎么刷销量 编辑:程序博客网 时间:2024/06/07 00:28
假期
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB
描述
经过几个月辛勤的工作,FJ决定让奶牛放假。假期可以在1…N天内任意选择一段(需要连续),每一天都有一个享受指数W。但是奶牛的要求非常苛刻,假期不能短于P天,否则奶牛不能得到足够的休息;假期也不能超过Q天,否则奶牛会玩的腻烦。FJ想知道奶牛们能获得的最大享受指数。
输入
第一行:N,P,Q.
第二行:N个数字,中间用一个空格隔开。
输出
一个整数,奶牛们能获得的最大享受指数。
样例输入
5 2 4
-9 -4 -3 8 -6
样例输出
5
提示
选择第3-4天,享受指数为-3+8=5。
50% 1≤N≤10000
100% 1≤N≤100000
1<=p<=q<=n
参考代码
#include <cstdio>#include <cstdlib>#include <cmath>#include <cstring>#include <string>#include <iostream>#include <algorithm>#include <vector>#include <stack>#include <queue>#include <deque>#include <map>#include <set>using std::cin;using std::cout;using std::endl;int n,p,q;long long num[100005];int main(){ scanf("%d%d%d",&n,&p,&q); for(int i=1; i<=n; i++) { scanf("%lld",&num[i]); num[i]+=num[i-1]; } int ans=0x80000000; std::deque<int> deq; //单调队列 //保存假期的起始点 //单调队列往往保存的是下标 for(int i=p; i<=n; i++) { //单调队列第一步:删去非最优解 //这一步最重要 //对于本题而言,如果把之前的数作为起始点还不如把当前点作为起始点,那就删了它 //如果前几个数的和比i-p对应的数还要大,说明num[j]-num[i-p]比num[j]-num[前几个数]要大 while(!deq.empty() && num[deq.back()] > num[i-p]) deq.pop_back(); //单调队列第二步:保存当前解 deq.push_back(i-p); //保存起始位置 //单调队列第三步:删去过时解 //这一步可以放在任何位置,但必须放在更新答案前 while(!deq.empty() && deq.front() < i-q) deq.pop_front(); //单调队列第四步:更新答案 //答案读取的是front,因为根据之前的操作front是最优解 ans=std::max(ans,int(num[i]-num[deq.front()])); } printf("%d",ans); return 0;}
阅读全文
0 0