#include <bits/stdc++.h>
#pragma GCC optimize("O3")
using namespace std;
template <class T>
void print(T& x) {
  cout << x;
}
template <class T, class U>
void print(pair<T, U>& p) {
  cout << "(";
  print(p.first);
  cout << ", ";
  print(p.second);
  cout << ")";
}
template <class T>
void print(vector<T>& v) {
  cout << "{";
  if (((int)(v).size())) print(v[0]);
  for (int i = 1; i < ((int)(v).size()); i++) cout << ", ", print(v[i]);
  cout << "}\n";
}
template <class T>
void print(deque<T>& v) {
  cout << "{";
  if (((int)(v).size())) print(v[0]);
  for (int i = 1; i < ((int)(v).size()); i++) cout << ", ", print(v[i]);
  cout << "}\n";
}
const long long inf = LLONG_MAX;
long long divide(long long a, long long b) {
  return a / b - ((a ^ b) < 0 && a % b);
}
struct line {
  long long a, b, r;
};
struct convex_hull : vector<line> {
  int p = 0;
  bool isect(line& x, line& y) {
    if (x.a == y.a)
      x.r = x.b > y.b ? inf : -inf;
    else
      x.r = divide(y.b - x.b, x.a - y.a);
    return x.r >= y.r;
  }
  void add(long long a, long long b) {
    line l = {a, b, inf};
    if (size() - p > 0 && isect(back(), l)) return;
    while (size() - p > 1 && (--(--end()))->r >= back().r)
      pop_back(), isect(back(), l);
    push_back(l);
  }
  long long query(long long x) {
    while (x > at(p).r) p++;
    return at(p).a * x + at(p).b;
  }
};
const int n = 90;
int INF = 1e8;
int N;
int dp[2][n][n * n];
vector<int> A;
vector<deque<int>> Q(3 * n * n);
int getVal(int sh, int n, int step, int ind) {
  int q0 = Q[step][ind];
  int v0 = dp[(sh & 1) ^ 1][q0][step - abs(A[sh] - q0)] +
           (n - q0) * (n - q0 - 1) / 2;
  return v0;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cin >> N;
  int cnt = 0;
  for (int i = 0; i < N; i++) {
    bool x;
    cin >> x;
    if (x)
      A.push_back(cnt);
    else
      cnt++;
  }
  INF = cnt * (cnt - 1) / 2;
  for (int i = 0; i <= cnt; i++) {
    for (int j = 0; j <= N * (N - 1) / 2; j++) {
      dp[1][i][j] = i * (i - 1) / 2;
    }
  }
  vector<int> bst(N * (N - 1) / 2 + 1, INF);
  for (int sh = 0; sh < ((int)(A).size()); sh++) {
    for (auto& q : Q) q.clear();
    for (int pos = 0; pos <= cnt; pos++) {
      for (int step = 0; step <= N * (N - 1) / 2; step++) {
        int qi = step + abs(A[sh] - pos);
        while (((int)(Q[qi]).size()) > 1) {
          Q[qi].push_back(pos);
          if (getVal(sh, pos, qi, ((int)(Q[qi]).size()) - 2) >=
              getVal(sh, pos, qi, ((int)(Q[qi]).size()) - 1)) {
            Q[qi].pop_back();
            Q[qi].pop_back();
          } else {
            Q[qi].pop_back();
            break;
          }
        }
        Q[qi].push_back(pos);
        dp[sh & 1][pos][step] = INF;
        if (((int)(Q[step]).size())) {
          while (((int)(Q[step]).size()) > 1 &&
                 getVal(sh, pos, step, 0) >= getVal(sh, pos, step, 1)) {
            Q[step].pop_front();
          }
          int v0 = getVal(sh, pos, step, 0);
          dp[sh & 1][pos][step] = v0;
        }
      }
    }
    for (int step = 0; step <= N * (N - 1) / 2; step++) {
      bst[step] = min(bst[step], dp[sh & 1][cnt][step]);
    }
  }
  cnt = cnt * (cnt - 1) / 2;
  for (int j = 0; j <= N * (N - 1) / 2; j++) {
    cout << max(0, cnt - bst[j]) << " ";
  }
  cout << endl;
}
