#include <bits/stdc++.h>
using namespace std;
void solve(std::istream &in, std::ostream &out);
int main() {
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.tie(nullptr);
  solve(std::cin, std::cout);
  return 0;
}
class tree_t {
  vector<int64_t> max_value;
  vector<int64_t> second_max;
  vector<int64_t> max_cnt;
  vector<int64_t> min_value;
  vector<int64_t> second_min;
  vector<int64_t> min_cnt;
  vector<int64_t> sum;
  vector<int64_t> tag_min;
  vector<int64_t> tag_max;
  vector<int64_t> tag_range;
  int n;
  void apply_push(int x, int64_t val, int type, int len) {
    if (min_value[x] == max_value[x] || type == 0) {
      tag_range[x] += val;
      sum[x] += val * len;
      min_value[x] += val;
      max_value[x] += val;
      if (second_max[x] != numeric_limits<int64_t>::min()) {
        second_max[x] += val;
      }
      if (second_min[x] != numeric_limits<int64_t>::max()) {
        second_min[x] += val;
      }
    } else if (type == 1) {
      min_value[x] += val;
      second_max[x] = max(second_max[x], min_value[x]);
      sum[x] += val * min_cnt[x];
      tag_min[x] += val;
    } else if (type == 2) {
      max_value[x] += val;
      second_min[x] = min(second_min[x], max_value[x]);
      sum[x] += val * max_cnt[x];
      tag_max[x] += val;
    }
    if (min_value[x] == max_value[x]) {
      second_max[x] = numeric_limits<int64_t>::min();
      second_min[x] = numeric_limits<int64_t>::max();
    }
  }
  void discharge(int x, int z, int len) {
    if (tag_range[x]) {
      apply_push(x + 1, tag_range[x], 0, len / 2);
      apply_push(z, tag_range[x], 0, len - len / 2);
    }
    tag_range[x] = 0;
    if (tag_min[x]) {
      if (min_value[x + 1] == min_value[x] - tag_min[x]) {
        apply_push(x + 1, tag_min[x], 1, len / 2);
      }
      if (min_value[z] == min_value[x] - tag_min[x]) {
        apply_push(z, tag_min[x], 1, len - len / 2);
      }
    }
    tag_min[x] = 0;
    if (tag_max[x]) {
      if (max_value[x + 1] == max_value[x] - tag_max[x]) {
        apply_push(x + 1, tag_max[x], 2, len / 2);
      }
      if (max_value[z] == max_value[x] - tag_max[x]) {
        apply_push(z, tag_max[x], 2, len - len / 2);
      }
    }
    tag_max[x] = 0;
  }
  void update(int x, int z) {
    sum[x] = sum[x + 1] + sum[z];
    if (min_value[x + 1] < min_value[z]) {
      min_value[x] = min_value[x + 1];
      second_min[x] = min(second_min[x + 1], min_value[z]);
      min_cnt[x] = min_cnt[x + 1];
    } else if (min_value[x + 1] > min_value[z]) {
      min_value[x] = min_value[z];
      second_min[x] = min(second_min[z], min_value[x + 1]);
      min_cnt[x] = min_cnt[z];
    } else if (min_value[x + 1] == min_value[z]) {
      min_value[x] = min_value[x + 1];
      second_min[x] = min(second_min[x + 1], second_min[z]);
      min_cnt[x] = min_cnt[x + 1] + min_cnt[z];
    }
    if (max_value[x + 1] > max_value[z]) {
      max_value[x] = max_value[x + 1];
      second_max[x] = max(second_max[x + 1], max_value[z]);
      max_cnt[x] = max_cnt[x + 1];
    } else if (max_value[x + 1] < max_value[z]) {
      max_value[x] = max_value[z];
      second_max[x] = max(second_max[z], max_value[x + 1]);
      max_cnt[x] = max_cnt[z];
    } else if (max_value[x + 1] == max_value[z]) {
      max_value[x] = max_value[x + 1];
      second_max[x] = max(second_max[x + 1], second_max[z]);
      max_cnt[x] = max_cnt[x + 1] + max_cnt[z];
    }
  }
  void build(int x, int l, int r, const function<int64_t(int)> &init_val) {
    if (l + 1 == r) {
      max_value[x] = init_val(l);
      second_max[x] = numeric_limits<int64_t>::min();
      max_cnt[x] = 1;
      min_value[x] = init_val(l);
      second_min[x] = numeric_limits<int64_t>::max();
      min_cnt[x] = 1;
      sum[x] = min_value[x];
      tag_min[x] = 0;
      tag_max[x] = 0;
      tag_range[x] = 0;
      return;
    }
    int y = (l + r) / 2, z = x + 2 * (y - l);
    build(x + 1, l, y, init_val);
    build(z, y, r, init_val);
    update(x, z);
  }
  void chmin(int x, int l, int r, int ql, int qr, int64_t val) {
    if (max_value[x] <= val) {
      return;
    } else if (ql <= l && r <= qr && second_max[x] < val) {
      assert(val - max_value[x] < 0);
      apply_push(x, val - max_value[x], 2, r - l);
      return;
    }
    int y = (l + r) / 2, z = x + 2 * (y - l);
    discharge(x, z, r - l);
    if (qr <= y) {
      chmin(x + 1, l, y, ql, qr, val);
    } else if (ql >= y) {
      chmin(z, y, r, ql, qr, val);
    } else {
      chmin(x + 1, l, y, ql, qr, val);
      chmin(z, y, r, ql, qr, val);
    }
    update(x, z);
  }
  void chmax(int x, int l, int r, int ql, int qr, int64_t val) {
    if (min_value[x] >= val) {
      return;
    } else if (ql <= l && r <= qr && second_min[x] > val) {
      assert(val - min_value[x] > 0);
      apply_push(x, val - min_value[x], 1, r - l);
      return;
    }
    int y = (l + r) / 2, z = x + 2 * (y - l);
    discharge(x, z, r - l);
    if (qr <= y) {
      chmax(x + 1, l, y, ql, qr, val);
    } else if (ql >= y) {
      chmax(z, y, r, ql, qr, val);
    } else {
      chmax(x + 1, l, y, ql, qr, val);
      chmax(z, y, r, ql, qr, val);
    }
    update(x, z);
  }
  void add_range(int x, int l, int r, int ql, int qr, int64_t val) {
    if (ql <= l && r <= qr) {
      apply_push(x, val, 0, r - l);
      return;
    }
    int y = (l + r) / 2, z = x + 2 * (y - l);
    discharge(x, z, r - l);
    if (qr <= y) {
      add_range(x + 1, l, y, ql, qr, val);
    } else if (ql >= y) {
      add_range(z, y, r, ql, qr, val);
    } else {
      add_range(x + 1, l, y, ql, qr, val);
      add_range(z, y, r, ql, qr, val);
    }
    update(x, z);
  }
  int64_t query(int x, int l, int r, int ql, int qr) {
    if (ql <= l && r <= qr) {
      return sum[x];
    }
    int y = (l + r) / 2, z = x + 2 * (y - l);
    discharge(x, z, r - l);
    if (qr <= y) {
      return query(x + 1, l, y, ql, qr);
    } else if (ql >= y) {
      return query(z, y, r, ql, qr);
    } else {
      return query(x + 1, l, y, ql, qr) + query(z, y, r, ql, qr);
    }
  }

 public:
  explicit tree_t(int n, const function<int64_t(int)> &init_val) : n(n) {
    max_value.resize(2 * n - 1);
    second_max.resize(2 * n - 1);
    max_cnt.resize(2 * n - 1);
    min_value.resize(2 * n - 1);
    second_min.resize(2 * n - 1);
    min_cnt.resize(2 * n - 1);
    sum.resize(2 * n - 1);
    tag_min.resize(2 * n - 1);
    tag_max.resize(2 * n - 1);
    tag_range.resize(2 * n - 1);
    build(0, 0, n, init_val);
  }
  int64_t query(int l, int r) { return query(0, 0, n, l, r); }
  void chmax(int l, int r, int64_t val) { chmax(0, 0, n, l, r, val); }
  void chmin(int l, int r, int64_t val) { chmin(0, 0, n, l, r, val); }
  void add_range(int l, int r, int64_t val) { add_range(0, 0, n, l, r, val); }
};
void solve(std::istream &in, std::ostream &out) {
  int n;
  in >> n;
  vector<int64_t> a(n);
  function<int64_t(int)> init_val = [&](int l) { return a[l]; };
  string s;
  in >> s;
  tree_t tree(n, init_val);
  int64_t ans = 0;
  int run = 0;
  for (int i = 0; i < n; ++i) {
    if (s[i] == '1') {
      ++run;
    } else {
      run = 0;
    }
    if (run) {
      tree.add_range(i - run, i + 1, 1);
      tree.chmax(0, i - run, run);
    }
    ans += tree.query(0, i + 1);
  }
  out << ans << '\n';
}
