链接:https://ac.nowcoder.com/acm/contest/134/H
来源:牛客网
题目描述
有 n 个盒子摆成一排,每个盒子内都有ai 个糖果。
现在你可以执行以下操作:
-
你可以选择任意一个盒子,在选择的盒子内吃掉一个糖果。
对你的要求如下:
-
任何m个相邻的盒子内糖果数量不能超过x个。
请问,实现要求的最少操作次数是多少?
输入描述
第一行三个数字n, m, x(2 ≤ n,m ≤ 106,1 ≤ x ≤ 109)。
第二行 n 个数字**(1 ≤ ai ≤ 109)**。
输出描述
输出一个操作数,代表实现要求的最少操作数。
输入
3 2 3
2 1 2
输出
0
说明
2 1 2满足题目要求,任意相邻的两个数值之和均不超过3,所以不需要进行任何操作。
算法分析
本题是典型的贪心算法,根据样例和题目要求,可以很明显的看出:糖果应该从后往前吃
因为越往后的糖果盒子,会与更多的盒子组成相邻的盒子子序列,从后向前减少的过程,就是尽可能的最大化的利用吃糖果的次数
注意!!!
如果这道题,暴力的去从后往前遍历减糖果,会超时!!! 因此需要使用子序列的滑动窗口算法! |
解题代码
#include <iostream>
using namespace std;
typedef long long ll;
const int MAX = 1e6 + 5;
int main(){
ll n,m,x;
cin >> n >> m >> x;
ll a[MAX],cnt = 0,sum = 0;
for(int i = 1; i <= n; i++){
cin>>a[i];
sum += a[i];
if(i>m) sum -= a[i-m]; //滑动窗口
//使得所有的m长度的子串和都小于x
if(sum > x){
a[i] -= sum - x;
cnt += sum - x;
sum = x;
}
}
cout << cnt << endl;
}