P5019 铺设道路

Luogu 链接

题意

题目描述

给定一个自然数序列,一次操作给定两个数 \(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\) 的目的。

程序

AC 记录

#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;
}
posted @ 2025-03-09 09:40  LXcjh4998  阅读(17)  评论(0)    收藏  举报