#include <bits/stdc++.h>
using namespace std;
bool debug;
template <typename T>
struct SegmentTreeMin {
 public:
  vector<T> st, A, lazy;
  int n;
  T SENTINEL = numeric_limits<T>::min();
  SegmentTreeMin(vector<T> _arr) {
    A = _arr;
    n = A.size();
    st.assign(4 * n, 0);
    lazy.assign(4 * n, SENTINEL);
    build(1, 0, n - 1);
  }
  T rangeQuery(int i, int j) { return rangeQuery(1, 0, n - 1, i, j); }
  void updateRange(int i, int j, T val) { updateRange(1, 0, n - 1, i, j, val); }

 private:
  int left(int p) { return p << 1; }
  int right(int p) { return (p << 1) | 1; }
  void build(int p, int l, int r) {
    if (l == r)
      st[p] = A[l];
    else {
      build(left(p), l, (l + r) / 2);
      build(right(p), (l + r) / 2 + 1, r);
      st[p] = merge(st[left(p)], st[right(p)]);
    }
  }
  T rangeQuery(int p, int l, int r, int i, int j) {
    propagate(p, l, r);
    if (i > r || j < l) return SENTINEL;
    if (l >= i && r <= j) return st[p];
    T p1, p2;
    p1 = rangeQuery(left(p), l, (l + r) / 2, i, j);
    p2 = rangeQuery(right(p), (l + r) / 2 + 1, r, i, j);
    return merge(p1, p2);
  }
  void propagate(int p, int l, int r) {
    if (lazy[p] != SENTINEL) {
      st[p] += lazy[p];
      if (l != r) {
        if (lazy[left(p)] != SENTINEL)
          lazy[left(p)] += lazy[p];
        else
          lazy[left(p)] = lazy[p];
        if (lazy[right(p)] != SENTINEL)
          lazy[right(p)] += lazy[p];
        else
          lazy[right(p)] = lazy[p];
      }
      lazy[p] = SENTINEL;
    }
  }
  void updateRange(int p, int l, int r, int i, int j, T val) {
    propagate(p, l, r);
    if (i > r || j < l)
      return;
    else if (l >= i && r <= j) {
      lazy[p] = val;
      propagate(p, l, r);
    } else {
      updateRange(left(p), l, (l + r) / 2, i, j, val);
      updateRange(right(p), (l + r) / 2 + 1, r, i, j, val);
      st[p] = merge(st[left(p)], st[right(p)]);
    }
  }
  T merge(T leftChild, T rightChild) {
    T parent = numeric_limits<T>::max();
    if (leftChild != SENTINEL) parent = min(parent, leftChild);
    if (rightChild != SENTINEL) parent = min(parent, rightChild);
    return parent;
  }
};
SegmentTreeMin<int> *st;
vector<int> arr;
long long solve(int l, int r, int terkurang) {
  long long tot = 0;
  int idx = l;
  while (idx <= r) {
    while (idx <= r && arr[idx] - terkurang == 0) {
      idx++;
    }
    if (idx > r) break;
    int kanan = idx;
    while (kanan <= r && arr[kanan] - terkurang > 0) {
      kanan++;
    }
    kanan--;
    int mini = st->rangeQuery(idx, kanan);
    long long costDivide = mini - terkurang;
    int idx2 = idx;
    while (idx2 <= kanan) {
      while (idx2 <= kanan && arr[idx2] - mini == 0) {
        idx2++;
      }
      if (idx2 > kanan) break;
      int kanan2 = idx2;
      while (kanan2 <= kanan && arr[kanan2] - mini > 0) {
        kanan2++;
      }
      kanan2--;
      costDivide += solve(idx2, kanan2, mini);
      idx2 = kanan2 + 1;
    }
    tot += min((long long)kanan - idx + 1, costDivide);
    idx = kanan + 1;
  }
  return tot;
}
int main(int argc, char *argv[]) {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  debug = argc > 1;
  int n;
  cin >> n;
  arr.resize(n);
  for (int i = 0; i < n; i++) {
    cin >> arr[i];
  }
  st = new SegmentTreeMin<int>(arr);
  cout << solve(0, n - 1, 0) << endl;
  return 0;
}
