用c++完成这道题:给定一个长度为 NN 的数列 A_{1}, A_{2}, \cdots, A_{N}A 1 ,A 2 ,⋯,A N 。现在小蓝想通过若干次操作将 这个数列中每个数字清零。 每次操作小蓝可以选择以下两种之一: 选择一个大于 0 的整数, 将它减去 1 ; 选择连续 KK 个大于 0 的整数, 将它们各减去 1 。 小蓝最少经过几次操作可以将整个数列清零?
时间: 2023-06-10 22:03:50 浏览: 256
C++语言算法:大整数去掉N个数使其值最小
这道题可以使用贪心算法进行求解。具体思路是:对于每个数A[i],我们尽量消耗掉它前面的数字,使得它可以通过减去若干个数字转化为0。这可以通过从后向前遍历数组A,并维护一个能够被当前数字A[i]所减至0的区间[L,R]实现。具体的,我们可以按以下步骤处理每个数字A[i]:
1. 如果A[i]=0,直接跳过。
2. 如果A[i]>0,我们可以选择将它减1或者使用区间[L,R]中的数减1。如果区间[L,R]中存在数字x使得x>A[i],那么显然必须选择将A[i]减1。否则,我们可以选择把A[i]减至0,然后更新区间[L,R]为[L+i,R+i-1],即将区间整体向后移动i位。
对于每个数字A[i],我们可以在O(1)的时间内处理出它对应的区间[L,R],所以总的时间复杂度为O(N)。以下是C++的实现代码:
```c++
#include <bits/stdc++.h>
using namespace std;
int n, a[100005];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
int ans = 0, r = n;
for (int i = n; i >= 1; i--) {
if (a[i] == 0) continue;
int l = max(i - a[i] + 1, 1);
if (l <= r) r = l - 1;
while (a[l] > 0) {
int k = min(a[l], r - l + 1);
r = l - 1;
a[l] -= k;
if (a[l] == 0) break;
r++;
}
if (a[i] > 0) ans++;
}
cout << ans << endl;
return 0;
}
```
阅读全文