P5019 铺设道路
题意
题目描述
给定一个自然数序列,一次操作给定两个数 \(L\) 和 \(R\),使区间 \([L,R]\) 全部数减 \(1\),且不允许出现负数。
问将序列变为 \(0\) 至少需要几次操作。
输入格式
第一行一个整数 \(n\)(\(1\le n\le10^5\)),代表序列的长度。
第二行 \(n\) 个整数 \(a_i\)(\(0\le a_i\le10^4\)),代表给出的序列。
输出格式
见题目描述。
思路
考虑贪心。设序列的第 \(i\) 项为 \(a_i\),且该序列有 \(n\) 项,将答案保存在 \(ans\) 里。则当 \(a_{i-1}<a_i\) 时,\(ans\) 加上 \(a_i-a_{i-1}\)。别忘了对 \(ans\) 赋初值 \(a_1\)(为了将 \(a_1\) 变成 \(0\))。
为什么这种贪心是正确的呢?我们可以对其感性理解下。
如果有 \(a_{i-1}\geq a_i\),则在将 \(a_{i-1}\) 减至 \(0\) 时,我们也可以顺带将 \(a_i\) 减至 \(0\),所得的答案一定不会更劣;如果 \(a_{i-1}<a_i\),则需要再用 \(a_i-a_{i-1}\) 次操作将 \(a_i\) 变成 \(0\)。
例如,对于样例,模拟的结果如下:
- \(ans=a_1=4\);
- \(a_1\geq a_2\),\(ans\) 不变;
- \(a_2\geq a_3\),\(ans\) 不变;
- \(a_3<a_4\),\(ans\) 加上 \(a_4-a_3\),得 \(ans=7\);
- \(a_4\geq a_5\),\(ans\) 不变;
- \(a_5<a_6\),\(ans\) 加上 \(a_6-a_5\),得 \(ans=9\)。
所以输出结果为:
9
实现上,可以令 \(a_0=0\)。对于 \(a_1\),显然有 \(a_0<a_1\),所以 \(ans\) 会加上 \(a_1-a_0\),即加上 \(a_1\),就达到了给 \(ans\) 赋初值 \(a_1\) 的目的。
程序
#include<bits/stdc++.h>
using namespace std;
int n,arr[100001],ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d",&arr[i]);
for(int i=1;i<=n;++i)if(arr[i-1]<arr[i])ans+=arr[i]-arr[i-1];//贪心
printf("%d",ans);
return 0;
}

浙公网安备 33010602011771号