洛谷 [P1714] 切蛋糕 (单调队列)

链接

https://www.luogu.org/problemnew/show/P1714

题意

给你一个长度为 n n n的整数序列,需要你求出区间长度不超过 k k k的最大区间和;

分析

  首先得到前缀和 s u m sum sum,对于最大区间和,我们即要求 max ⁡ ( s u m [ i ] − s u m [ j ] ) ( i − j &lt; = k ) \max(sum[i]-sum[j])(i-j&lt;=k) max(sum[i]sum[j])(ij<=k),这里可以用线段树、树状数组求,对于每个 i i i来说,我们只需要求最小的 s u m [ j ] sum[j] sum[j],其中 j ∈ [ i − k , i ] j\in[i-k,i] j[ik,i],即转换为一个求区间最小值问题;
  但是这里有一种 O ( n ) O(n) O(n)的方法,使用单调队列维护递增的长度为 k k k s u m sum sum,对于当前入队的 s u m sum sum来说,在它入队之前的所有状态的最值已经求出来了,现在我们可以利用它来继续更新,让队尾大于它的元素出队,并且不满足区间长度 k k k的从队首出队;当前 s u m sum sum入队之后,我们就用队首 s u m sum sum减队尾 s u m sum sum(因为队列 s u m sum sum递增),来更新我们的最大区间和;队列元素为下标,另外 s u m [ 0 ] sum[0] sum[0]也要考虑;

代码
#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>

#define INF 0x7f7f7f7f
#define MAXN 1000005
#define N 200005
#define P 2
#define MOD 99991

typedef long long ll;

namespace fastIO {
	//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
	//char buf[(1 << 22)], *p1 = buf, *p2 = buf;
	inline int read() {
		char c = getchar(); int x = 0, f = 1;
		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;
	}
}

using namespace fastIO;
using namespace std;

int n, k, sum[MAXN];
int q[MAXN], h, t;
int main() {
	cin >> n >> k;
	int x;
	for (int i = 1; i <= n; i++)
		cin >> x, sum[i] += sum[i - 1] + x;
	h = 1;
	int res = 0;
	for (int i = 0; i <= n; i++) {
		while (h <= t && i - q[h] > k)h++;
		while (h <= t && sum[q[t]] >= sum[i])t--;
		q[++t] = i;
		res = max(res, sum[i] - sum[q[h]]);
	}
	cout << res << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值