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;
}
此生无悔入OI 来生AK IOI

浙公网安备 33010602011771号