P1714

切蛋糕

题目描述

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

小 Z 作为寿星,自然希望吃到的蛋糕的幸运值总和最大,但小 Z 最多又只能吃 \(m(m\le n)\) 小块的蛋糕。

请你帮他从这 \(n\) 小块中找出连续\(k(1 \le k\le m)\) 块蛋糕,使得其上的总幸运值最大。

形式化地,在数列 \(\{p_n\}\) 中,找出一个子段 \([l,r](r-l+1\le m)\),最大化 \(\sum\limits_{i=l}^rp_i\)

输入格式

第一行两个整数 \(n,m\)。分别代表共有 \(n\) 小块蛋糕,小 Z 最多只能吃 \(m\) 小块。

第二行 \(n\) 个整数,第 \(i\) 个整数 \(p_i\) 代表第 \(i\) 小块蛋糕的幸运值。

输出格式

仅一行一个整数,即小 Z 能够得到的最大幸运值。

样例 #1

样例输入 #1

5 2
1 2 3 4 5

样例输出 #1

9

样例 #2

样例输入 #2

6 3
1 -2 3 -4 5 -6

样例输出 #2

5

提示

数据规模与约定

对于 \(20\%\) 的数据,有 \(1\le n\le100\)
对于 \(100\%\) 的数据,有 \(1\le n\le5\times 10^5\)\(|p_i|≤500\)

这题就是维护一个区间长为m的前缀和的单调队列
每次s[i]-s[q[l]]即可 注意要考虑s[i]-s[0]的情况
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m,a[500005],s[500005],q[500005],l=1,r=0;
signed main()
{
	n=read(),m=read();
	for(register int i=1;i<=n;++i)
		a[i]=read(),s[i]=s[i-1]+a[i];
	int maxx=-LONG_MAX;
	for(int i=1;i<=n;i++)
	{
		while(l<=r&&s[q[r]]>=s[i])
			r--;
		q[++r]=i;
		while(l<=r&&q[r]-q[l]>m)
			l++;
//		cout<<s[q[l]]<<"   "<<s[i]<<"\n";
		if(i<=m)maxx=max(maxx,s[i]);
		maxx=max(maxx,s[i]-s[q[l]]);
	}
	cout<<maxx<<"\n";
	return 0;
}
posted @ 2023-01-16 13:04  PKU_IMCOMING  阅读(9)  评论(0)    收藏  举报