贪心 | 铺设道路c++
春春希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为。铺设道路的主要工作是填平下陷的地表。输出文件仅包含一个整数,即最少需要多少天才能完成任务。,填充这段区间中的每块区域,让其下陷深度减少。春春是一名道路工程师,负责铺设一条长度为。个整数,相邻两数间用一个空格隔开,第。输入文件包含两行,第一行包含一个整数。NOI
P5019 [NOIP 2018 提高组] 铺设道路
题目背景
NOIP2018 提高组 D1T1
题目描述
春春是一名道路工程师,负责铺设一条长度为 n n n 的道路。
铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n n n 块首尾相连的区域,一开始,第 i i i 块区域下陷的深度为 d i d_i di 。
春春每天可以选择一段连续区间 [ L , R ] [L,R] [L,R] ,填充这段区间中的每块区域,让其下陷深度减少 1 1 1。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为 0 0 0 。
春春希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为 0 0 0 。
输入格式
输入文件包含两行,第一行包含一个整数 n n n,表示道路的长度。 第二行包含 n n n 个整数,相邻两数间用一个空格隔开,第 i i i 个整数为 d i d_i di 。
输出格式
输出文件仅包含一个整数,即最少需要多少天才能完成任务。
输入输出样例 #1
输入 #1
6
4 3 2 5 3 5
输出 #1
9
说明/提示
【样例解释】
一种可行的最佳方案是,依次选择:
[ 1 , 6 ] [1,6] [1,6]、 [ 1 , 6 ] [1,6] [1,6]、 [ 1 , 2 ] [1,2] [1,2]、 [ 1 , 1 ] [1,1] [1,1]、 [ 4 , 6 ] [4,6] [4,6]、 [ 4 , 4 ] [4,4] [4,4]、 [ 4 , 4 ] [4,4] [4,4]、 [ 6 , 6 ] [6,6] [6,6]、 [ 6 , 6 ] [6,6] [6,6]。
【数据规模与约定】
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 10 1 ≤ n ≤ 10 1≤n≤10 ;
对于 70 % 70\% 70% 的数据, 1 ≤ n ≤ 1000 1 ≤ n ≤ 1000 1≤n≤1000 ;
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 100000 , 0 ≤ d i ≤ 10000 1 ≤ n ≤ 100000 , 0 ≤ d_i ≤ 10000 1≤n≤100000,0≤di≤10000 。
题解
//题解:
//贪心策略:对于每个区域,若其深度大于前一个区域,则多出的部分必须通过额外的天数来处理
//因此,答案总天数等于第一个区域的深度加上所有相邻区域的正差之和
//是不是难以理解,接下来逐一解释为什么是 第一个区域的深度 + 所有相邻区域的正差之和
//先看这个例子
//4 3 2 5 3 5
//所有减去2为:
//2 1 0 3 1 3
//.....
//1 0 0 2 0 2
//通过上面的过程我们可以看出,较大的几个值一定最后填充,
//所有相邻区域的正差之和解释:
//题目说我们可以连续填充,但是当遇到一段中有0就不能连续填充,发生了截断,截断的原因不就是当前的深度大于前一个区域
//所以我们可以之间看深度最大的,因为填大的可以顺便带着填完前面的深度小的
//那取的天数为什么是所有相邻区域的正差之和(a[i]-a[i-1]),不直接是当前深度a[i]呢?
//我们看例子 [2 1 0 3 1 3] 这时候的状态[0 3]这一段是不是要填a[i]-a[i-1]差值才可以变成[0 0]
//这时候就有人问了,[0 3]的第一个数还需要变成0啊
//这就要解释答案为什么还要加上第一个区域的深度
//加上第一个区域的深度解释:
//第一个区域有两种情况,要么大于第二个区域深度,要么小于等于第二个区域深度
//先看大于的情况
//[4 2 5] -> [2 0 3] 我们只求相邻区域的正差之和(a[i]-a[i-1]时候),那a[i-1]这时候是算到了a[1]头上的,a[1]剩下的深度最后也加上了
//再看小于等于情况
//[2 4 2] -> [0 2 0] 是不是也将数第一次有深度变成0的情况都可以算到a[1]的头上
//所以加上第一个区域的深度可以看作 第一次有深度变成0的天数 + 第一个区域的深度比较大还剩余要填充的天数
//所以答案为:第一个区域的深度 + 所有相邻区域的正差之和
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
int n, a[100005], ans;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
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;
}
更多推荐




所有评论(0)