返回题目
由于雨水冲刷,长度为N的路面下陷。勤劳的养路工人使用机器恢复路面,机器每天只能对一段路面[L,R]之间的区域进行1个单位深度的填充修补,道路的
路况用下陷的深度表示。请编程输出修好这条路至少需要的天数。
【输入形式】
第一行一个整数N;
第二行N个空格隔开的整数,表示路面的下陷程度。
【输出形式】
一个整数,表示所用的天数。
【样例输入】
6
1 3 2 4 5 3
【样例输出】
6
【样例说明】
6天修补[1,6], [2,6], [2,2], [4,6], [4,5], [5,5]路段即可。
【评分标准】
0<N<100000;
输出正确的答案。
1
它就是一个贪心。
题目里给的样例是4,3,2,5,3,5;
可以选择一个区间进行“填坑”操作;
所以我们的贪心策略是:
若a[i]>a[i-1],计数器sum+=a[i]-a[i-1];
那么为什么这样贪心是对的呢?
贪心证明
假设现在有一个坑,但旁边又有一个坑。
你肯定会选择把两个同时减1;
那么小的坑肯定会被大的坑“带着”填掉。
大的坑也会减少a[i]-a[i-1]的深度,可以说是“免费的”;
所以这样贪心是对的;
代码
#include<bits/stdc++.h>
using namespace std;
int n,a[100005];
long long ans=0;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=2;i<=n;i++) if(a[i]>a[i-1]) ans+=a[i]-a[i-1];
cout<<ans+a[1];
return 0;
}
记得要加上a[1],或者在前面填一个0; (这是本蒟蒻第一次写题解,支持一下哦。)
2
#include <cstdio>
#include <algorithm>
using namespace std;
int a[100010];
int main()
{
int n;
scanf("%d",&n);
int minn=0x3f3f3f3f;
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
if(a[i]<minn)minn=a[i];
}
for(int i=1;i<=n;++i)
a[i]-=minn;
long long sum=minn;
int k=0;
for(int i=1;;++i)//未知次操作
{
if(!a[k])
{
k++;
if(k==n+1)break;
}//遍历非0段
int minx=a[k];
for(int j=k;j<=n;++j)
{
if(!a[j])break;
if(a[j]<minx)minx=a[j];
}
for(int j=k;j<=n;++j)
{
if(!a[j])break;
a[j]-=minx;
}//处理
sum+=minx;
}
printf("%lld\n",sum);
return 0;
}