#include <bits/stdc++.h>
using namespace std;
void __print(int x) { cerr << x; }
void __print(long x) { cerr << x; }
void __print(long long x) { cerr << x; }
void __print(unsigned x) { cerr << x; }
void __print(unsigned long x) { cerr << x; }
void __print(unsigned long long x) { cerr << x; }
void __print(float x) { cerr << x; }
void __print(double x) { cerr << x; }
void __print(long double x) { cerr << x; }
void __print(char x) { cerr << '\'' << x << '\''; }
void __print(const char *x) { cerr << '\"' << x << '\"'; }
void __print(const string &x) { cerr << '\"' << x << '\"'; }
void __print(bool x) { cerr << (x ? "true" : "false"); }
template <typename T, typename V>
void __print(const pair<T, V> &x) {
  cerr << '{';
  __print(x.first);
  cerr << ',';
  __print(x.second);
  cerr << '}';
}
template <typename T>
void __print(const T &x) {
  int f = 0;
  cerr << '{';
  for (auto &i : x) cerr << (f++ ? "," : ""), __print(i);
  cerr << "}";
}
void _print() { cerr << "]\n"; }
template <typename T, typename... V>
void _print(T t, V... v) {
  __print(t);
  if (sizeof...(v)) cerr << ", ";
  _print(v...);
}
const int mod = 1000000007;
int n;
struct node {
  int maxx, minn, lazy;
  node() {
    maxx = 0;
    minn = 0;
    lazy = 0;
  }
  node(int x, int y, int z) {
    maxx = x;
    minn = y;
    lazy = z;
  }
};
vector<node> segtree;
vector<int> v;
void handle_lazy(int i, int tl, int tr) {
  segtree[i].maxx += segtree[i].lazy;
  segtree[i].minn += segtree[i].lazy;
  if (tl != tr) {
    segtree[2 * i].lazy += segtree[i].lazy;
    segtree[2 * i + 1].lazy += segtree[i].lazy;
  }
  segtree[i].lazy = 0;
}
node query(int i, int tl, int tr, int l, int r) {
  if (l > tr || r < tl) return node(INT_MIN, INT_MAX, 0);
  handle_lazy(i, tl, tr);
  if (tl >= l && tr <= r) return segtree[i];
  int tm = (tl + tr) / 2;
  node left = query(2 * i, tl, tm, l, r);
  node right = query(2 * i + 1, tm + 1, tr, l, r);
  node ans;
  ans.maxx = max(left.maxx + left.lazy, right.maxx + right.lazy);
  ans.minn = min(left.minn + left.lazy, right.minn + right.lazy);
  return ans;
}
void update(int i, int tl, int tr, int l, int r, int val) {
  if (l > tr || r < tl)
    return;
  else if (tl >= l && tr <= r) {
    segtree[i].lazy += val;
    handle_lazy(i, tl, tr);
    return;
  } else {
    int tm = (tl + tr) / 2;
    update(2 * i, tl, tm, l, r, val);
    update(2 * i + 1, tm + 1, tr, l, r, val);
  }
  segtree[i].maxx = max(segtree[2 * i].maxx + segtree[2 * i].lazy,
                        segtree[2 * i + 1].maxx + segtree[2 * i + 1].lazy);
  segtree[i].minn = min(segtree[2 * i].minn + segtree[2 * i].lazy,
                        segtree[2 * i + 1].minn + segtree[2 * i + 1].lazy);
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n;
  string s;
  cin >> s;
  v.assign(n, 0);
  segtree.resize(4 * n + 1);
  int index = 0;
  string curr;
  for (int i = 1; i <= n; i++) curr.push_back('a');
  for (int i = 0; i < n; i++) {
    int val = 0;
    if (s[i] == '(') {
      if (curr[index] == ')')
        val = 2;
      else if (islower(curr[index]))
        val = 1;
      update(1, 0, n - 1, index, n - 1, val);
      curr[index] = '(';
    } else if (s[i] == ')') {
      if (curr[index] == '(')
        val = -2;
      else if (islower(curr[index]))
        val = -1;
      update(1, 0, n - 1, index, n - 1, val);
      curr[index] = ')';
    } else if (s[i] == 'R')
      index++;
    else if (s[i] == 'L') {
      if (index != 0) index--;
    } else {
      if (curr[index] == '(')
        update(1, 0, n - 1, index, n - 1, -1);
      else if (curr[index] == ')')
        update(1, 0, n - 1, index, n - 1, 1);
      curr[index] = s[i];
    }
    node q_entire = query(1, 0, n - 1, 0, n - 1);
    node q_end = query(1, 0, n - 1, n - 1, n - 1);
    if (q_entire.minn < 0 || q_end.maxx != 0)
      cout << -1 << " ";
    else
      cout << q_entire.maxx << " ";
  }
  return 0;
}
