/*
题目链接: http://codeforces.com/contest/448/problem/C
代码参考:
http://blog.csdn.net/u013076044/article/details/41808899
这个代码逻辑清楚
题目大意:
给出n个杆子,每个杆子有一个长度,每次可以刷一行或一列,问最少刷多少次可以将整个墙刷成黄色。
就是分治
ans = min{ 1.区间长度(全部竖着刷);
2.先横着把底部连在一起的全刷了,剩下的在递归调用函数,然后加起来; }
首先,我们假如每次都刷一个木板,即一竖行,那么需要n次刷完,
可见这是一个ans的最大值。就是最差的情况下我这样刷最多为n刷。
其次:如果我们选择一横行的刷,而n个木板中最短的为min,那么我们可以花min刷,把他们都刷成a[i]-min的高度,
那么剩下来的栅栏又变成了开始的情况。
然后,继续按上面的方法刷,可见是一个递归调用。
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <string>
#include <sstream>
#include <map>
#include <set>
#define pi acos(-1.0)
#define LL long long
#define ULL unsigned long long
#define inf 0x3f3f3f3f
#define INF 1e18
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define debug(a) printf("---%d---\n", a)
#define mem0(a) memset(a, 0, sizeof(a))
#define memi(a) memset(a, inf, sizeof(a))
#define mem1(a) memset(a, -1, sizeof(a))
#define input1(a) scanf("%d", &a)
#define input2(a,b) scanf("%d %d", &a, &b)
#define input3(a,b,c) scanf("%d %d %d", &a, &b, &c)
using namespace std;
typedef pair<int, int> P;
const double eps = 1e-10;
const int maxn = 1e6 + 5;
const int N = 1e4 + 5;
const int mod = 1e8;
int h[maxn];
int n, ans;
int solve(int l, int r) // 区间 [l, r]
{
int mi = inf;
for (int i = l; i <= r; i++)
mi = min(mi, h[i]);
for (int i = l; i <= r; i++)
h[i] -= mi;
int sum = mi, sta = l;
for (int i = l; i <= r; i++){
if (h[i] == 0){
if (sta == i){ // 如果当前高度就为0 直接跳过
sta++;
continue;
}
sum += solve(sta, i-1); // 分治 区间[sta, i-1]
sta = i + 1;
}
}
if (h[r] != 0) sum += solve(sta, r); // 最后一个特别讨论
return min(sum, r-l+1); // 答案为两者中较小的
}
int main(void)
{
// freopen("in.txt","r", stdin);
cin >> n;
int min_ = inf;
for (int i = 1; i <= n; i++)
cin >> h[i];
cout << solve(1, n) << endl;
return 0;
}