#include <bits/stdc++.h>
using namespace std;
class SegmTreeMax {
 private:
  int n;
  vector<int> tree;
  vector<int> lazy;
  void shift(int node) {
    lazy[2 * node] += lazy[node];
    lazy[2 * node + 1] += lazy[node];
    tree[2 * node] += lazy[node];
    tree[2 * node + 1] += lazy[node];
    lazy[node] = 0;
  }
  void update(int node, int left, int right, int uLeft, int uRight, int val) {
    if (left == uLeft && right == uRight) {
      lazy[node] += val;
      tree[node] += val;
      return;
    }
    shift(node);
    int mid = (left + right) / 2;
    if (uRight <= mid)
      update(2 * node, left, mid, uLeft, uRight, val);
    else if (uLeft > mid)
      update(2 * node + 1, mid + 1, right, uLeft, uRight, val);
    else {
      update(2 * node, left, mid, uLeft, mid, val);
      update(2 * node + 1, mid + 1, right, mid + 1, uRight, val);
    }
    tree[node] = max(tree[2 * node], tree[2 * node + 1]);
  }
  int query(int node, int left, int right, int qLeft, int qRight) {
    if (left == qLeft && right == qRight) return tree[node];
    shift(node);
    int mid = (left + right) / 2;
    if (qRight <= mid)
      return query(2 * node, left, mid, qLeft, qRight);
    else if (qLeft > mid)
      return query(2 * node + 1, mid + 1, right, qLeft, qRight);
    return max(query(2 * node, left, mid, qLeft, mid),
               query(2 * node + 1, mid + 1, right, mid + 1, qRight));
  }

 public:
  SegmTreeMax(int n) {
    this->n = n;
    tree.resize(4 * n);
    lazy.resize(4 * n);
  }
  void update(int left, int right, int val) {
    update(1, 1, n, left, right, val);
  }
  int query(int left, int right) { return query(1, 1, n, left, right); }
};
class SegmTreeMin {
 private:
  int n;
  vector<int> tree;
  vector<int> lazy;
  void shift(int node) {
    lazy[2 * node] += lazy[node];
    lazy[2 * node + 1] += lazy[node];
    tree[2 * node] += lazy[node];
    tree[2 * node + 1] += lazy[node];
    lazy[node] = 0;
  }
  void update(int node, int left, int right, int uLeft, int uRight, int val) {
    if (left == uLeft && right == uRight) {
      lazy[node] += val;
      tree[node] += val;
      return;
    }
    shift(node);
    int mid = (left + right) / 2;
    if (uRight <= mid)
      update(2 * node, left, mid, uLeft, uRight, val);
    else if (uLeft > mid)
      update(2 * node + 1, mid + 1, right, uLeft, uRight, val);
    else {
      update(2 * node, left, mid, uLeft, mid, val);
      update(2 * node + 1, mid + 1, right, mid + 1, uRight, val);
    }
    tree[node] = min(tree[2 * node], tree[2 * node + 1]);
  }
  int query(int node, int left, int right, int qLeft, int qRight) {
    if (left == qLeft && right == qRight) return tree[node];
    shift(node);
    int mid = (left + right) / 2;
    if (qRight <= mid)
      return query(2 * node, left, mid, qLeft, qRight);
    else if (qLeft > mid)
      return query(2 * node + 1, mid + 1, right, qLeft, qRight);
    return min(query(2 * node, left, mid, qLeft, mid),
               query(2 * node + 1, mid + 1, right, mid + 1, qRight));
  }

 public:
  SegmTreeMin(int n) {
    this->n = n;
    tree.resize(4 * n);
    lazy.resize(4 * n);
  }
  void update(int left, int right, int val) {
    update(1, 1, n, left, right, val);
  }
  int query(int left, int right) { return query(1, 1, n, left, right); }
};
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  SegmTreeMax treeMax(n);
  SegmTreeMin treeMin(n);
  string str;
  str.resize(n + 1);
  int crt = 1;
  set<int> phar;
  for (int i = 0; i < n; i++) {
    char chr;
    cin >> chr;
    if (chr == 'L') {
      if (--crt < 1) crt = 1;
    } else if (chr == 'R')
      crt++;
    else if (chr == '(') {
      if (str[crt] == ')') {
        treeMax.update(crt, n, +2);
        treeMin.update(crt, n, +2);
      } else if (str[crt] != '(') {
        treeMax.update(crt, n, +1);
        treeMin.update(crt, n, +1);
      }
      str[crt] = chr;
      phar.insert(crt);
    } else if (chr == ')') {
      if (str[crt] == '(') {
        treeMax.update(crt, n, -2);
        treeMin.update(crt, n, -2);
      } else if (str[crt] != ')') {
        treeMax.update(crt, n, -1);
        treeMin.update(crt, n, -1);
      }
      str[crt] = chr;
      phar.insert(crt);
    } else {
      if (str[crt] == '(') {
        treeMax.update(crt, n, -1);
        treeMin.update(crt, n, -1);
        phar.erase(crt);
      } else if (str[crt] == ')') {
        treeMax.update(crt, n, +1);
        treeMin.update(crt, n, +1);
        phar.erase(crt);
      }
      str[crt] = chr;
    }
    if (!phar.empty() &&
        treeMin.query(*(phar.rbegin()), *(phar.rbegin())) == 0 &&
        treeMin.query(1, *(phar.rbegin())) >= 0)
      cout << treeMax.query(1, *(phar.rbegin())) << ' ';
    else if (phar.empty())
      cout << "0 ";
    else
      cout << "-1 ";
  }
  cout << '\n';
  return 0;
}
