单调队列

来源:互联网 发布:淘宝新店怎么刷销量 编辑:程序博客网 时间: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;}
原创粉丝点击