洛谷 P1714 切蛋糕

洛谷 P1714 切蛋糕

Description

  • 今天是小Z的生日,同学们为他带来了一块蛋糕。这块蛋糕是一个长方体,被用不同色彩分成了N个相同的小块,每小块都有对应的幸运值。

    小Z作为寿星,自然希望吃到的第一块蛋糕的幸运值总和最大,但小Z最多又只能吃M小块(M≤N)的蛋糕。

    吃东西自然就不想思考了,于是小Z把这个任务扔给了学OI的你,请你帮他从这N小块中找出连续的k块蛋糕(k≤M),使得其上的幸运值最大。

Input

  • 输入文件cake.in的第一行是两个整数N,M。分别代表共有N小块蛋糕,小Z最多只能吃M小块。

    第二行用空格隔开的N个整数,第i个整数Pi代表第i小块蛋糕的幸运值。

Output

  • 输出文件cake.out只有一行,一个整数,为小Z能够得到的最大幸运值。

Sample Input

6 3
1 -2 3 -4 5 -6

Sample Output

5

Data Size

  • 对20%的数据,N≤100。

    对100%的数据,N≤500000,|Pi|≤500。 答案保证在2^31-1之内。

题解:

  • 单调队列。

  • 因为序列是连续的,而且不停的在滑动。所以我就想到了单调队列。然后我就想着普通dp怎么写?首先求一个前缀和,那么枚举右端点,右端点确定了,就在位置(右端点 - m) ~ 位置(右端点)之间找一个最小的前缀和。两数一减,每个右端点取一次max。那么复杂度是O(nm)。既然想到了用单调队列,那么优化掉找最小前缀和这一步就好了。

#include <iostream>
#include <cstdio>
#include <deque>
#define N 500005
using namespace std;

struct Node {int val, pos;};
deque<Node> que;
int n, m, ans = -0x7fffffff;
int sum[N];

int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
    return x *= f;
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        sum[i] = read();
        sum[i] += sum[i - 1];
    }
    que.push_back((Node){0, 0});
    for(int i = 1; i <= n; i++)
    {
        ans = max(ans, sum[i] - que.front().val);
        while(que.size() && que.front().pos + m <= i) que.pop_front();
        while(que.size() && que.back().val >= sum[i]) que.pop_back();
        que.push_back((Node){sum[i], i});
    }
    cout << ans;
    return 0;
}

转载于:https://www.cnblogs.com/BigYellowDog/p/11386231.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值