#include <bits/stdc++.h>
using namespace std;

template<class Monoid, class OperatorMonoid = Monoid>
struct LazySegmentTree {
    using FunctionM = Monoid(*) (Monoid, Monoid);
    using FunctionMO = Monoid(*) (Monoid, OperatorMonoid, int); // 3rd param = length;
    using FunctionO = OperatorMonoid(*) (OperatorMonoid, OperatorMonoid);

    static constexpr int N = 1 << 20;
    Monoid segment[2 * N];
    OperatorMonoid lazy[2 * N];
    const FunctionM FuncM; const FunctionMO FuncMO; const FunctionO FuncO;
    const Monoid idM; const OperatorMonoid idOM;

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        fill_n(segment, 2 * N, idM); fill_n(lazy, 2 * N, idOM);
    }

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM, const Monoid initVal)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        fill_n(segment, 2 * N, initVal); fill_n(lazy, 2 * N, idOM);
    }

    void set(int num, Monoid x) {
        segment[N + num] = x;
    }
    void build() {
        for (int k = N - 1; k > 0; k--) {
            segment[k] = FuncM(segment[2*k], segment[2*k+1]);
        }
    }

    inline void propagate(int k, int len){
        if (lazy[k] != idOM) {
            if (k < N) {
                lazy[2*k] = FuncO(lazy[2*k], lazy[k]);
                lazy[2*k+1] = FuncO(lazy[2*k+1], lazy[k]);
            }
            segment[k] = FuncMO(segment[k], lazy[k], len);
            lazy[k] = idOM;
        }
    }

    // update:[a, b)
    Monoid update(int a, int b, const OperatorMonoid x) {
        return update(a, b, x, 1, 0, N);
    }
    Monoid update(int a, int b, const OperatorMonoid x, int k, int l, int r){
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return segment[k];
        } else if (a <= l && r <= b) {
            lazy[k] = FuncO(lazy[k], x);
            propagate(k, r-l);
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return segment[k] = FuncM(update(a, b, x, 2*k, l, m), update(a, b, x, 2*k+1, m, r));
        }
    }

    // query:[a, b)
    Monoid query(int a, int b) {
        return query(a, b, 1, 0, N);
    }
    Monoid query(int a, int b, int k, int l, int r) {
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return idM;
        } else if (a <= l && r <= b) {
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return FuncM(query(a, b, 2*k, l, m), query(a, b, 2*k+1, m, r));
        }
    }

    // 0-indexed numbering;
    inline Monoid operator[](const int &k) {
        return query(k, k + 1);
    }
};

pair<int, int> F(pair<int, int> a, pair<int, int> b) { return {min(a.first, b.first), max(a.second, b.second)}; };
pair<int, int> G(pair<int, int> a, int b, int len) {return {a.first + b, a.second + b};}
int H(int a, int b) {return a + b;}
pair<int, int> id = {1e9, -1e9}, zero = {0, 0};

int v[1000000];
int ans[1000000];

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    LazySegmentTree<pair<int, int>, int> lst(n, F, G, H, id, 0, zero);
    string s; cin >> s;
    int curr = 0; int j = 0;
    for (auto &c: s) {
        if (c == 'R') {
            curr++;
        } else if (c == 'L') {
            if (curr) curr--;
        } else {
            int a = c == '(' ? 1 : c == ')' ? -1 : 0;
            if (a != v[curr]) {
                lst.update(curr, n, a - v[curr]);
                v[curr] = a;
            }
        }
        auto cq = lst.query(0, n);
        if (cq.first < 0 || lst[n-1].first) ans[j++] = -1;
        else ans[j++] = cq.second;
    }
    for (int i = 0; i < n; i++) {
        cout << ans[i] << " ";
    }
    cout << "\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<class Monoid, class OperatorMonoid = Monoid>
struct LazySegmentTree {
    using FunctionM = Monoid(*) (Monoid, Monoid);
    using FunctionMO = Monoid(*) (Monoid, OperatorMonoid, int); // 3rd param = length;
    using FunctionO = OperatorMonoid(*) (OperatorMonoid, OperatorMonoid);

    static constexpr int N = 1 << 20;
    Monoid segment[2 * N];
    OperatorMonoid lazy[2 * N];
    const FunctionM FuncM; const FunctionMO FuncMO; const FunctionO FuncO;
    const Monoid idM; const OperatorMonoid idOM;

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        fill_n(segment, 2 * N, idM); fill_n(lazy, 2 * N, idOM);
    }

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM, const Monoid initVal)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        fill_n(segment, 2 * N, initVal); fill_n(lazy, 2 * N, idOM);
    }

    void set(int num, Monoid x) {
        segment[N + num] = x;
    }
    void build() {
        for (int k = N - 1; k > 0; k--) {
            segment[k] = FuncM(segment[2*k], segment[2*k+1]);
        }
    }

    inline void propagate(int k, int len){
        if (lazy[k] != idOM) {
            if (k < N) {
                lazy[2*k] = FuncO(lazy[2*k], lazy[k]);
                lazy[2*k+1] = FuncO(lazy[2*k+1], lazy[k]);
            }
            segment[k] = FuncMO(segment[k], lazy[k], len);
            lazy[k] = idOM;
        }
    }

    // update:[a, b)
    Monoid update(int a, int b, const OperatorMonoid x) {
        return update(a, b, x, 1, 0, N);
    }
    Monoid update(int a, int b, const OperatorMonoid x, int k, int l, int r){
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return segment[k];
        } else if (a <= l && r <= b) {
            lazy[k] = FuncO(lazy[k], x);
            propagate(k, r-l);
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return segment[k] = FuncM(update(a, b, x, 2*k, l, m), update(a, b, x, 2*k+1, m, r));
        }
    }

    // query:[a, b)
    Monoid query(int a, int b) {
        return query(a, b, 1, 0, N);
    }
    Monoid query(int a, int b, int k, int l, int r) {
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return idM;
        } else if (a <= l && r <= b) {
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return FuncM(query(a, b, 2*k, l, m), query(a, b, 2*k+1, m, r));
        }
    }

    // 0-indexed numbering;
    inline Monoid operator[](const int &k) {
        return query(k, k + 1);
    }
};

pair<int, int> F(pair<int, int> a, pair<int, int> b) { return {min(a.first, b.first), max(a.second, b.second)}; };
pair<int, int> G(pair<int, int> a, int b, int len) {return {a.first + b, a.second + b};}
int H(int a, int b) {return a + b;}
pair<int, int> id = {1e9, -1e9}, zero = {0, 0};

int v[1000000];
vector<int> ans;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    LazySegmentTree<pair<int, int>, int> lst(n, F, G, H, id, 0, zero);
    string s; cin >> s;
    int curr = 0; int j = 0;
    for (auto &c: s) {
        if (c == 'R') {
            curr++;
        } else if (c == 'L') {
            if (curr) curr--;
        } else {
            int a = c == '(' ? 1 : c == ')' ? -1 : 0;
            if (a != v[curr]) {
                lst.update(curr, n, a - v[curr]);
                v[curr] = a;
            }
        }
        auto cq = lst.query(0, n);
        if (cq.first < 0 || lst[n-1].first) ans.emplace_back(-1);
        else ans.emplace_back(cq.second);
    }
    for (int i = 0; i < n; i++) {
        cout << ans[i] << " ";
    }
    cout << "\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<class Monoid, class OperatorMonoid = Monoid>
struct LazySegmentTree {
    using FunctionM = Monoid(*)(Monoid, Monoid);
    using FunctionMO = Monoid(*)(Monoid, OperatorMonoid, int); // 3rd param = length;
    using FunctionO = OperatorMonoid(*)(OperatorMonoid, OperatorMonoid);

    int N; vector<Monoid> segment; vector<OperatorMonoid> lazy;
    const FunctionM FuncM; const FunctionMO FuncMO; const FunctionO FuncO;
    const Monoid idM; const OperatorMonoid idOM;

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        N = 1;
        while (N < n) N <<= 1;
        segment.assign(2 * N, idM); lazy.assign(2 * N, idOM);
    }

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM, const Monoid initVal)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        N = 1;
        while (N < n) N <<= 1;
        segment.assign(2 * N, initVal); lazy.assign(2 * N, idOM);
    }

    void set(int num, Monoid x) {
        segment[N + num] = x;
    }
    void build() {
        for (int k = N - 1; k > 0; k--) {
            segment[k] = FuncM(segment[2*k], segment[2*k+1]);
        }
    }

    inline void propagate(int k, int len){
        if (lazy[k] != idOM) {
            if (k < N) {
                lazy[2*k] = FuncO(lazy[2*k], lazy[k]);
                lazy[2*k+1] = FuncO(lazy[2*k+1], lazy[k]);
            }
            segment[k] = FuncMO(segment[k], lazy[k], len);
            lazy[k] = idOM;
        }
    }

    // update:[a, b)
    Monoid update(int a, int b, const OperatorMonoid x) {
        return update(a, b, x, 1, 0, N);
    }
    Monoid update(int a, int b, const OperatorMonoid x, int k, int l, int r){
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return segment[k];
        } else if (a <= l && r <= b) {
            lazy[k] = FuncO(lazy[k], x);
            propagate(k, r-l);
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return segment[k] = FuncM(update(a, b, x, 2*k, l, m), update(a, b, x, 2*k+1, m, r));
        }
    }

    // query:[a, b)
    Monoid query(int a, int b) {
        return query(a, b, 1, 0, N);
    }
    Monoid query(int a, int b, int k, int l, int r) {
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return idM;
        } else if (a <= l && r <= b) {
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return FuncM(query(a, b, 2*k, l, m), query(a, b, 2*k+1, m, r));
        }
    }

    // 0-indexed numbering;
    Monoid operator[](const int &k) {
        return query(k, k + 1);
    }
};

int F(int a, int b) { return min(a, b); };
int E(int a, int b) { return max(a, b); };
int G(int a, int b, int len) {return a + b;}
int H(int a, int b) {return a + b;}

int v[1000000];
int ans[1000000];

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    LazySegmentTree<int> lst(n, F, G, H, 1e9, 0, 0), xlst(n, E, G, H, -1e9, 0, 0);
    string s; cin >> s;
    int curr = 0; int j = 0;
    for (auto &c: s) {
        if (c == '(') {
            if (1 - v[curr]) {
                lst.update(curr, n, 1 - v[curr]);
                xlst.update(curr, n, 1 - v[curr]);
            }
            v[curr] = 1;
        } else if (c == ')') {
            if (-1 - v[curr]) {
                lst.update(curr, n, -1 - v[curr]);
                xlst.update(curr, n, -1 - v[curr]);
            }
            v[curr] = -1;
        } else if (c == 'R') {
            curr++;
        } else if (c == 'L') {
            if (curr) curr--;
        } else {
            if (v[curr]) {
                lst.update(curr, n, -v[curr]);
                xlst.update(curr, n, -v[curr]);
            }
            v[curr] = 0;
        }
        int mini = lst.query(0, n);
        if (mini < 0 || lst[n-1]) ans[j++] = -1;
        else ans[j++] = xlst.query(0, n);
    }
    for (int i = 0; i < n; i++) {
        if (i) cout << " ";
        cout << ans[i];
    }
    cout << "\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<class Monoid, class OperatorMonoid = Monoid>
struct LazySegmentTree {
    using FunctionM = Monoid(*) (Monoid, Monoid);
    using FunctionMO = Monoid(*) (Monoid, OperatorMonoid, int); // 3rd param = length;
    using FunctionO = OperatorMonoid(*) (OperatorMonoid, OperatorMonoid);

    int N; vector<Monoid> segment; vector<OperatorMonoid> lazy;
    const FunctionM FuncM; const FunctionMO FuncMO; const FunctionO FuncO;
    const Monoid idM; const OperatorMonoid idOM;

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        N = 1;
        while (N < n) N <<= 1;
        segment.assign(2 * N, idM); lazy.assign(2 * N, idOM);
    }

    void set(int num, Monoid x) {
        segment[N + num] = x;
    }
    void build() {
        for (int k = N - 1; k > 0; k--) {
            segment[k] = FuncM(segment[2*k], segment[2*k+1]);
        }
    }

    inline void propagate(int k, int len){
        if (lazy[k] != idOM) {
            if (k < N) {
                lazy[2*k] = FuncO(lazy[2*k], lazy[k]);
                lazy[2*k+1] = FuncO(lazy[2*k+1], lazy[k]);
            }
            segment[k] = FuncMO(segment[k], lazy[k], len);
            lazy[k] = idOM;
        }
    }

    // update:[a, b)
    Monoid update(int a, int b, const OperatorMonoid x) {
        return update(a, b, x, 1, 0, N);
    }
    Monoid update(int a, int b, const OperatorMonoid x, int k, int l, int r){
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return segment[k];
        } else if (a <= l && r <= b) {
            lazy[k] = FuncO(lazy[k], x);
            propagate(k, r-l);
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return segment[k] = FuncM(update(a, b, x, 2*k, l, m), update(a, b, x, 2*k+1, m, r));
        }
    }

    // query:[a, b)
    Monoid query(int a, int b) {
        return query(a, b, 1, 0, N);
    }
    Monoid query(int a, int b, int k, int l, int r) {
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return idM;
        } else if (a <= l && r <= b) {
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return FuncM(query(a, b, 2*k, l, m), query(a, b, 2*k+1, m, r));
        }
    }

    // 0-indexed numbering;
    Monoid operator[](const int &k) {
        return query(k, k + 1);
    }
};

pair<int, int> F(pair<int, int> a, pair<int, int> b) { return {min(a.first, b.first), max(a.second, b.second)}; };
pair<int, int> G(pair<int, int> a, int b, int len) {return {a.first + b, a.second + b};}
int H(int a, int b) {return a + b;}
pair<int, int> id = {1e9, -1e9}, zero = {0, 0};

int v[1000000];
int ans[1000000];

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    LazySegmentTree<pair<int, int>, int> lst(n, F, G, H, id, 0);
    for (int i = 0; i < n; i++) lst.set(i, zero);
    lst.build();
    string s; cin >> s;
    int curr = 0; int j = 0;
    for (auto &c: s) {
        if (c == '(') {
            if (1 - v[curr]) {
                lst.update(curr, n, 1 - v[curr]);
            }
            v[curr] = 1;
        } else if (c == ')') {
            if (-1 - v[curr]) {
                lst.update(curr, n, -1 - v[curr]);
            }
            v[curr] = -1;
        } else if (c == 'R') {
            curr++;
        } else if (c == 'L') {
            if (curr) curr--;
        } else {
            if (v[curr]) {
                lst.update(curr, n, -v[curr]);
            }
            v[curr] = 0;
        }
        auto cq = lst.query(0, n);
        if (cq.first < 0 || lst[n-1].first) ans[j++] = -1;
        else ans[j++] = cq.second;
    }
    for (int i = 0; i < n; i++) {
        if (i) cout << " ";
        cout << ans[i];
    }
    cout << "\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<class Monoid, class OperatorMonoid = Monoid>
struct LazySegmentTree {
    using FunctionM = Monoid(*)(Monoid, Monoid);
    using FunctionMO = Monoid(*)(Monoid, OperatorMonoid, int); // 3rd param = length;
    using FunctionO = OperatorMonoid(*)(OperatorMonoid, OperatorMonoid);

    int N; vector<Monoid> segment; vector<OperatorMonoid> lazy;
    const FunctionM FuncM; const FunctionMO FuncMO; const FunctionO FuncO;
    const Monoid idM; const OperatorMonoid idOM;

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        N = 1;
        while (N < n) N <<= 1;
        segment.assign(2 * N, idM); lazy.assign(2 * N, idOM);
    }

    void set(int num, Monoid x) {
        segment[N + num] = x;
    }
    void build() {
        for (int k = N - 1; k > 0; k--) {
            segment[k] = FuncM(segment[2*k], segment[2*k+1]);
        }
    }

    inline void propagate(int k, int len){
        if (lazy[k] != idOM) {
            if (k < N) {
                lazy[2*k] = FuncO(lazy[2*k], lazy[k]);
                lazy[2*k+1] = FuncO(lazy[2*k+1], lazy[k]);
            }
            segment[k] = FuncMO(segment[k], lazy[k], len);
            lazy[k] = idOM;
        }
    }

    // update:[a, b)
    Monoid update(int a, int b, const OperatorMonoid x) {
        return update(a, b, x, 1, 0, N);
    }
    Monoid update(int a, int b, const OperatorMonoid x, int k, int l, int r){
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return segment[k];
        } else if (a <= l && r <= b) {
            lazy[k] = FuncO(lazy[k], x);
            propagate(k, r-l);
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return segment[k] = FuncM(update(a, b, x, 2*k, l, m), update(a, b, x, 2*k+1, m, r));
        }
    }

    // query:[a, b)
    Monoid query(int a, int b) {
        return query(a, b, 1, 0, N);
    }
    Monoid query(int a, int b, int k, int l, int r) {
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return idM;
        } else if (a <= l && r <= b) {
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return FuncM(query(a, b, 2*k, l, m), query(a, b, 2*k+1, m, r));
        }
    }

    // 0-indexed numbering;
    Monoid operator[](const int &k) {
        return query(k, k + 1);
    }
};

int F(int a, int b) { return min(a, b); };
int E(int a, int b) { return max(a, b); };
int G(int a, int b, int len) {return a + b;}
int H(int a, int b) {return a + b;}

int v[1000000];
int ans[1000000];

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    LazySegmentTree<int> lst(n, F, G, H, 1e9, 0, 0), xlst(n, E, G, H, -1e9, 0, 0);
    string s; cin >> s;
    int curr = 0; int j = 0;
    for (auto &c: s) {
        if (c == '(') {
            if (1 - v[curr]) {
                lst.update(curr, n, 1 - v[curr]);
                xlst.update(curr, n, 1 - v[curr]);
            }
            v[curr] = 1;
        } else if (c == ')') {
            if (-1 - v[curr]) {
                lst.update(curr, n, -1 - v[curr]);
                xlst.update(curr, n, -1 - v[curr]);
            }
            v[curr] = -1;
        } else if (c == 'R') {
            curr++;
        } else if (c == 'L') {
            if (curr) curr--;
        } else {
            if (v[curr]) {
                lst.update(curr, n, -v[curr]);
                xlst.update(curr, n, -v[curr]);
            }
            v[curr] = 0;
        }
        int mini = lst.query(0, n);
        if (mini < 0 || lst[n-1]) ans[j++] = -1;
        else ans[j++] = xlst.query(0, n);
    }
    for (int i = 0; i < n; i++) {
        if (i) cout << " ";
        cout << ans[i];
    }
    cout << "\n";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

template<class Monoid, class OperatorMonoid = Monoid>
struct LazySegmentTree {
    using FunctionM = Monoid(*) (Monoid, Monoid);
    using FunctionMO = Monoid(*) (Monoid, OperatorMonoid, int); // 3rd param = length;
    using FunctionO = OperatorMonoid(*) (OperatorMonoid, OperatorMonoid);

    static constexpr int N = 1 << 17;
    Monoid segment[2 * N];
    OperatorMonoid lazy[2 * N];
    const FunctionM FuncM; const FunctionMO FuncMO; const FunctionO FuncO;
    const Monoid idM; const OperatorMonoid idOM;

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        fill_n(segment, 2 * N, idM); fill_n(lazy, 2 * N, idOM);
    }

    LazySegmentTree(int n, const FunctionM FuncM, const FunctionMO FuncMO, const FunctionO FuncO,
        const Monoid idM, const OperatorMonoid idOM, const Monoid initVal)
    : FuncM(FuncM), FuncMO(FuncMO), FuncO(FuncO), idM(idM), idOM(idOM) {
        fill_n(segment, 2 * N, initVal); fill_n(lazy, 2 * N, idOM);
    }

    void set(int num, Monoid x) {
        segment[N + num] = x;
    }
    void build() {
        for (int k = N - 1; k > 0; k--) {
            segment[k] = FuncM(segment[2*k], segment[2*k+1]);
        }
    }

    inline void propagate(int k, int len){
        if (lazy[k] != idOM) {
            if (k < N) {
                lazy[2*k] = FuncO(lazy[2*k], lazy[k]);
                lazy[2*k+1] = FuncO(lazy[2*k+1], lazy[k]);
            }
            segment[k] = FuncMO(segment[k], lazy[k], len);
            lazy[k] = idOM;
        }
    }

    // update:[a, b)
    Monoid update(int a, int b, const OperatorMonoid x) {
        return update(a, b, x, 1, 0, N);
    }
    Monoid update(int a, int b, const OperatorMonoid x, int k, int l, int r){
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return segment[k];
        } else if (a <= l && r <= b) {
            lazy[k] = FuncO(lazy[k], x);
            propagate(k, r-l);
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return segment[k] = FuncM(update(a, b, x, 2*k, l, m), update(a, b, x, 2*k+1, m, r));
        }
    }

    // query:[a, b)
    Monoid query(int a, int b) {
        return query(a, b, 1, 0, N);
    }
    Monoid query(int a, int b, int k, int l, int r) {
        propagate(k, r-l);
        if (b <= l || r <= a) {
            return idM;
        } else if (a <= l && r <= b) {
            return segment[k];
        } else {
            int m = (l + r) / 2;
            return FuncM(query(a, b, 2*k, l, m), query(a, b, 2*k+1, m, r));
        }
    }

    // 0-indexed numbering;
    inline Monoid operator[](const int &k) {
        return query(k, k + 1);
    }
};

pair<int, int> F(pair<int, int> a, pair<int, int> b) { return {min(a.first, b.first), max(a.second, b.second)}; };
pair<int, int> G(pair<int, int> a, int b, int len) {return {a.first + b, a.second + b};}
int H(int a, int b) {return a + b;}
pair<int, int> id = {1e9, -1e9}, zero = {0, 0};

int v[1000000];
vector<int> ans;

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n; cin >> n;
    LazySegmentTree<pair<int, int>, int> lst(n, F, G, H, id, 0, zero);
    string s; cin >> s;
    int curr = 0; int j = 0;
    for (auto &c: s) {
        if (c == 'R') {
            curr++;
        } else if (c == 'L') {
            if (curr) curr--;
        } else {
            int a = c == '(' ? 1 : c == ')' ? -1 : 0;
            if (a != v[curr]) {
                lst.update(curr, n, a - v[curr]);
                v[curr] = a;
            }
        }
        auto cq = lst.query(0, n);
        if (cq.first < 0 || lst[n-1].first) ans.emplace_back(-1);
        else ans.emplace_back(cq.second);
    }
    for (int i = 0; i < n; i++) {
        cout << ans[i] << " ";
    }
    cout << "\n";
    return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = n + 1) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = n + 1) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];

	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, n + 1, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, n + 1, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, n + 1, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, n + 1, -1);
			}
			s[cur] = i;
		}
		if (get(0, n + 1).mn > 0 && ted0 == ted1)
			cout << get(0, n + 1).mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[4 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = n + 1) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = n + 1) {
	if (lp >= rp)
		return trash;
	relax(v);
	if (lp == l && rp == r)
		return seg[v];

	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '+', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, n + 1, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, n + 1, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, n + 1, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, n + 1, -1);
			}
			s[cur] = i;
		}
		if (get(0, n + 1).mn >= 0 && ted0 == ted1)
			cout << get(0, n + 1).mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1500 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp || l == r)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
	relax(v);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp || l == r)
		return trash;
	if (lp == l && rp == r)
		return seg[v];
	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
	relax(v);
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, MAXN, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, MAXN, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, MAXN, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, MAXN, -1);
			}
			s[cur] = i;
		}
		relax(1);
		if (seg[1].mn >= 0 && ted0 == ted1 && seg[1].mx <= ted0)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1500 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
	relax(v);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];
	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
	relax(v);
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, MAXN, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, MAXN, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, MAXN, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, MAXN, -1);
			}
			s[cur] = i;
		}
		if (seg[1].mn >= 0 && ted0 == ted1 && seg[1].mx <= ted0)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];

	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, n + 1, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, n + 1, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, n + 1, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, n + 1, -1);
			}
			s[cur] = i;
		}
		if (seg[1].mn >= 0 && ted0 == ted1)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1500 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
	relax(v);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];
	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
	relax(v);
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, MAXN, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, MAXN, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, MAXN, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, MAXN, -1);
			}
			s[cur] = i;
		}
		relax(1);
		if (seg[1].mn >= 0 && ted0 == ted1 && seg[1].mx <= ted0)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second
#define inf long long
typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[4 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	if (2 * v < MAXN)
		lazy[2 * v] += lazy[v];
	if (2 * v + 1 < MAXN)
		lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
	relax(v);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];
	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
	relax(v);
}

int32_t main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, MAXN, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, MAXN, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, MAXN, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, MAXN, -1);
			}
			s[cur] = i;
		}
		if (seg[1].mn >= 0 && ted0 == ted1 && seg[1].mx <= ted0)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[4 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	if (2 * v < MAXN)
		lazy[2 * v] += lazy[v];
	if (2 * v + 1 < MAXN)
		lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
	relax(v);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];
	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
	relax(v);
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, MAXN, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, MAXN, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, MAXN, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, MAXN, -1);
			}
			s[cur] = i;
		}
		relax(1);
		if (seg[1].mn >= 0 && ted0 == ted1 && seg[1].mx <= ted0)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = n + 1) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = n + 1) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];

	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '+', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, n + 1, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, n + 1, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, n + 1, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, n + 1, -1);
			}
			s[cur] = i;
		}
		if (get(0, n + 1).mn >= 0 && ted0 == ted1)
			cout << get(0, n + 1).mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1500 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= r || rp <= l)
		return;
	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
	relax(v);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= r || rp <= l)
		return trash;
	if (lp == l && rp == r)
		return seg[v];
	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
	relax(v);
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, MAXN, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, MAXN, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, MAXN, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, MAXN, -1);
			}
			s[cur] = i;
		}
		relax(1);
		if (seg[1].mn >= 0 && ted0 == ted1)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx, lazy;
	node () {
		mn = 0;
		mx = 0;
		lazy = 0;
	}
	node operator+(const node &x) const {
		node res;
		res.mn = min(mn, x.mn);
		res.mx = max(mx, x.mx);
		return res;
	}
	void add_node(const int &x) {
		mn += x;
		mx += x;
		lazy += x;
	}
};

int n, ted;
node seg[4 * MAXN];
string cm;
char s[MAXN];

//0 (
//1 )

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = n) {
	if (lp >= r || rp <= l)
		return;
	if (lp <= l && r <= rp) {
		seg[v].add_node(val);
		return;
	}
	int mid = (l + r) / 2;
	seg[2 * v].add_node(seg[v].lazy);
	seg[2 * v + 1].add_node(seg[v].lazy);
	add(lp, rp, val, 2 * v, l, mid);
	add(lp, rp, val, 2 * v + 1, mid, r);
	seg[v] = seg[2 * v] + seg[2 * v + 1];
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted++;
				add(cur, n, -1);
			}
			else if (s[cur] == ')') {
				ted--;
				add(cur, n, 1);
			}
			if (i == '(') {
				ted--;
				add(cur, n, 1);
			}
			else if(i == ')') {
				ted++;
				add(cur, n, -1);
			}
			s[cur] = i;
		}
		if (seg[1].mn >= 0 && !ted)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


//IOI 2021
//this will accept, By the order of the peaky fucking blinders
#include <bits/stdc++.h>
using namespace std;

#define pb push_back
#define ff first
#define ss second

typedef long long ll;
typedef pair<int, int> pii;

const int MAXN = 1000 * 1000 + 17, inf = 1e9 + 17;

struct node {
	int mn, mx;
	node () {
		mn = 0;
		mx = 0;
	}
};

int n, ted0, ted1, lazy[8 * MAXN];
node seg[4 * MAXN], trash;
string cm;
char s[MAXN];

//0 (
//1 )

node mrge(node a, node b) {
	a.mx = max(a.mx, b.mx);
	a.mn = max(a.mn, b.mn);
	return a;
}

void relax(int v) {
	seg[v].mn += lazy[v];
	seg[v].mx += lazy[v];
	lazy[2 * v] += lazy[v];
	lazy[2 * v + 1] += lazy[v];
	lazy[v] = 0;
}

void add(int lp, int rp, int val, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return;

	if (lp == l && rp == r) {
		lazy[v] += val;
		relax(v);
		return;
	}
	int mid = (l + r) / 2;
	add(lp, min(mid, rp), val, 2 * v, l, mid);
	add(max(mid, lp), rp, val, 2 * v + 1, mid, r);
	seg[v] = mrge(seg[2 * v], seg[2 * v + 1]);
}

node get(int lp, int rp, int v = 1, int l = 0, int r = MAXN) {
	relax(v);
	if (lp >= rp)
		return trash;
	if (lp == l && rp == r)
		return seg[v];

	int mid = (l + r) / 2;
	return mrge(get(lp, min(mid, rp), 2 * v, l, mid),
			get(max(mid, lp), rp, 2 * v + 1, mid, r));
}

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	cin >> n >> cm;
	trash.mn = inf;
	trash.mx = -inf;
	memset(s, '$', sizeof(s));
	int cur = 0;
	for (auto i : cm) {
		if (i == 'L')
			cur--, cur = max(cur, 0);
		else if (i == 'R')
			cur++;
		else {
			if (s[cur] == '(') {
				ted0--;
				add(cur, MAXN, -1);
			}
			else if (s[cur] == ')') {
				ted1--;
				add(cur, MAXN, 1);
			}
			if (i == '(') {
				ted0++;
				add(cur, MAXN, 1);
			}
			else if(i == ')') {
				ted1++;
				add(cur, MAXN, -1);
			}
			s[cur] = i;
		}
		if (seg[1].mn >= 0 && ted0 == ted1)
			cout << seg[1].mx << ' ';
		else
			cout << -1 << ' ';

	}
	return 0;
}


#include <bits/stdc++.h>

// #include <boost/multiprecision/cpp_int.hpp>
// #define ll cpp_int
// using namespace boost::multiprecision;

using namespace std;
#define speedup ios::sync_with_stdio(0);cin.tie(0);
#define fileIO freopen("inp00.txt","r",stdin);freopen("out00.txt","w",stdout);
#define all(a) (a).begin(), (a).end()
#define ll long long
#define ld long double
#define pb push_back
#define mk make_pair
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define INF INT_MAX
#define imi -1e18
#define ima 1e18
#define err(...) fprintf(stderr, _VA_ARGS_),fflush(stderr)
#define PI 3.14159265359
const ll mod = 1e9 + 7;

// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// #include <functional>
// using namespace __gnu_pbds;
// typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> pbds;

ll expo(ll a,ll b,ll m){if(a==0) return 1;ll res=1;while(b){if(b%2==1)res=((res%m)*(a%m))%m;a=((a%m)*(a%m))%m;b/=2;}return res%m;}
ld expo2(ld a,ll b){ld res=1;while(b){if(b%2==1)res=(res*a);a=(a*a);b/=2;}return res;}
ll mulmod(ll a,ll b,ll m){if(a==0) return 1;ll res=0;while(b){if(b%2==1)res=((res%m)+(a%m))%m;a=((a%m)+(a%m))%m;b/=2;}return res%m;}

ll gcd(ll a,ll b) {
    if (b==0)
        return a;
    return gcd(b,a%b);
}
#include <bits/stdc++.h>
using namespace std;

const ll N = 1000010;

ll seg1[4*N];
ll seg2[4*N];
// ll seg3[4*N];
ll lazy[4*N];

// void buildTree(vector<ll> &seg,vector<ll> &arr,ll low, ll high, ll pos) {
//     if (low==high) {
//         seg[pos]=arr[low];
//         return;
//     }
//     ll mid = (low+high)/2;
//     buildTree(seg,arr,low,mid,2*pos+1);
//     buildTree(seg,arr,mid+1,high,2*pos+2);
//     seg[pos] = min(seg[2*pos+1],seg[2*pos+2]);
// }

pair<ll,ll> query(ll qlow,ll qhigh,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[2*pos+1] += lazy[pos];
            lazy[2*pos+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return mk(0,INT_MAX);
    } else if (qlow<=low && qhigh>=high){
        return mk(seg1[pos],seg2[pos]);
    }
    ll mid = (low+high)/2;
    pair<ll,ll> left=query(qlow,qhigh,low,mid,2*pos+1);
    pair<ll,ll> right=query(qlow,qhigh,mid+1,high,2*pos+2);
    return mk(max(left.fi,right.fi),min(left.se,right.se));
}

void updateRange(ll qlow,ll qhigh,ll val,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[2*pos+1] += lazy[pos];
            lazy[2*pos+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return;
    } else if (qlow<=low && qhigh>=high){
        seg1[pos] += val;
        seg2[pos] += val;
        if (low!=high) {
            lazy[2*pos+1] += val;
            lazy[2*pos+2] += val;
        }
        return;
    } else {
        ll mid = (low+high)/2;
        updateRange(qlow,qhigh,val,low,mid,2*pos+1);
        updateRange(qlow,qhigh,val,mid+1,high,2*pos+2);
        seg1[pos] = max(seg1[2*pos+1],seg1[2*pos+2]);
        seg2[pos] = min(seg2[2*pos+1],seg2[2*pos+2]);
    }
}

// ll querySum(ll qlow, ll qhigh, ll low, ll high, ll pos) {
//     if (qhigh<low || qlow>high)
//         return 0;
//     if (qlow<=low && qhigh>=high)
//         return seg3[pos];
//     ll mid = (low+high)/2;
//     ll a1 = querySum(qlow,qhigh,low,mid,2*pos+1);
//     ll a2 = querySum(qlow,qhigh,mid+1,high,2*pos+2);
//     return a1+a2;
// }

// void updatePoint(ll index,ll val,ll low, ll high, ll pos) {
//     if (low>high)
//         return;
//     if (low==high) {
//         seg3[pos]=val;
//         return;
//     }
//     ll mid = (low+high)/2;
//     if (index<=mid)
//         updatePoint(index,val,low,mid,2*pos+1);
//     else
//         updatePoint(index,val,mid+1,high,2*pos+2);
//     seg3[pos] = seg3[2*pos+1]+seg3[2*pos+2];
// }

int main() {
    speedup;
    ll n;
    cin>>n;

    string com;
    cin>>com;

    ll pos = 0;
    vector<ll> txt(n);
    for (int i=0;i<n;i++) {
        ll val = 0;
        ll val2 = 0;
        if (com[i]=='(') {
            val2 = 1;
            if (txt[pos]==')')
                val=2;
            else if (txt[pos]=='(')
                val=0;
            else
                val=1;
            txt[pos]='(';
        }
        else if (com[i]==')') {
            val2 = -1;
            if (txt[pos]=='(')
                val=-2;
            else if (txt[pos]==')')
                val=0;
            else
                val=-1;
            txt[pos]=')';
        }
        else if (com[i]>='a' && com[i]<='z') {
            if (txt[pos]=='(')
                val=-1;
            else if (txt[pos]==')')
                val=+1;
            else
                val=0;
            txt[pos]=com[i];
        }
        else if (com[i]=='L')
            pos = max(0ll,pos-1);
        else if (com[i]=='R')
            pos = pos+1;

        updateRange(pos,n-1,val,0,n-1,0);
        // updatePoint(pos,val2,0,n-1,0);

        pair<ll,ll> a1 = query(0,n-1,0,n-1,0);
        pair<ll,ll> a2 = query(n-1,n-1,0,n-1,0);

        if (a1.se>=0 && a2.se==0) {
            cout<<a1.fi<<" ";
        } else {
            cout<<"-1 ";
        }
    }
    cout<<endl;
    return 0;
}

/*
20
(R)R)R(R(RaR)R)R(R(R)
(   R   )   R   )   R   (   R   (   R   a   R   )   R   )   R   (   R   (   R   )
-1 -1   ?   ?   -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
())((a))(()
*/


#include <bits/stdc++.h>

// #include <boost/multiprecision/cpp_int.hpp>
// #define ll cpp_int
// using namespace boost::multiprecision;

using namespace std;
#define speedup ios::sync_with_stdio(0);cin.tie(0);
#define fileIO freopen("inp00.txt","r",stdin);freopen("out00.txt","w",stdout);
#define all(a) (a).begin(), (a).end()
#define ll long long
#define ld long double
#define pb push_back
#define mk make_pair
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define INF INT_MAX
#define imi -1e18
#define ima 1e18
#define err(...) fprintf(stderr, _VA_ARGS_),fflush(stderr)
#define PI 3.14159265359
const ll mod = 1e9 + 7;

// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// #include <functional>
// using namespace __gnu_pbds;
// typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> pbds;

ll expo(ll a,ll b,ll m){if(a==0) return 1;ll res=1;while(b){if(b%2==1)res=((res%m)*(a%m))%m;a=((a%m)*(a%m))%m;b/=2;}return res%m;}
ld expo2(ld a,ll b){ld res=1;while(b){if(b%2==1)res=(res*a);a=(a*a);b/=2;}return res;}
ll mulmod(ll a,ll b,ll m){if(a==0) return 1;ll res=0;while(b){if(b%2==1)res=((res%m)+(a%m))%m;a=((a%m)+(a%m))%m;b/=2;}return res%m;}

ll gcd(ll a,ll b) {
    if (b==0)
        return a;
    return gcd(b,a%b);
}
#include <bits/stdc++.h>
using namespace std;

const ll N = 1000010;

ll seg1[N<<2];
ll seg2[N<<2];
// ll seg3[4*N];
ll lazy[N<<2];

// void buildTree(vector<ll> &seg,vector<ll> &arr,ll low, ll high, ll pos) {
//     if (low==high) {
//         seg[pos]=arr[low];
//         return;
//     }
//     ll mid = (low+high)/2;
//     buildTree(seg,arr,low,mid,pos<<1|1);
//     buildTree(seg,arr,mid+1,high,(pos<<1)+2);
//     seg[pos] = min(seg[pos<<1|1],seg[(pos<<1)+2]);
// }

ll queryMax(ll qlow,ll qhigh,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[pos<<1|1] += lazy[pos];
            lazy[(pos<<1)+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return 0;
    } else if (qlow<=low && qhigh>=high){
        return seg1[pos];
    }
    ll mid = (low+high)/2;
    ll left=queryMax(qlow,qhigh,low,mid,pos<<1|1);
    ll right=queryMax(qlow,qhigh,mid+1,high,(pos<<1)+2);
    return max(left,right);
}

ll queryMin(ll qlow,ll qhigh,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[pos<<1|1] += lazy[pos];
            lazy[(pos<<1)+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return INT_MAX;
    } else if (qlow<=low && qhigh>=high){
        return seg2[pos];
    }
    ll mid = (low+high)/2;
    ll left=queryMin(qlow,qhigh,low,mid,pos<<1|1);
    ll right=queryMin(qlow,qhigh,mid+1,high,(pos<<1)+2);
    return min(left,right);
}

void updateRange(ll qlow,ll qhigh,ll val,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[pos<<1|1] += lazy[pos];
            lazy[(pos<<1)+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return;
    } else if (qlow<=low && qhigh>=high){
        seg1[pos] += val;
        seg2[pos] += val;
        if (low!=high) {
            lazy[pos<<1|1] += val;
            lazy[(pos<<1)+2] += val;
        }
        return;
    } else {
        ll mid = (low+high)/2;
        updateRange(qlow,qhigh,val,low,mid,pos<<1|1);
        updateRange(qlow,qhigh,val,mid+1,high,(pos<<1)+2);
        seg1[pos] = max(seg1[pos<<1|1],seg1[(pos<<1)+2]);
        seg2[pos] = min(seg2[pos<<1|1],seg2[(pos<<1)+2]);
    }
}

// ll querySum(ll qlow, ll qhigh, ll low, ll high, ll pos) {
//     if (qhigh<low || qlow>high)
//         return 0;
//     if (qlow<=low && qhigh>=high)
//         return seg3[pos];
//     ll mid = (low+high)/2;
//     ll a1 = querySum(qlow,qhigh,low,mid,pos<<1|1);
//     ll a2 = querySum(qlow,qhigh,mid+1,high,(pos<<1)+2);
//     return a1+a2;
// }

// void updatePoint(ll index,ll val,ll low, ll high, ll pos) {
//     if (low>high)
//         return;
//     if (low==high) {
//         seg3[pos]=val;
//         return;
//     }
//     ll mid = (low+high)/2;
//     if (index<=mid)
//         updatePoint(index,val,low,mid,pos<<1|1);
//     else
//         updatePoint(index,val,mid+1,high,(pos<<1)+2);
//     seg3[pos] = seg3[pos<<1|1]+seg3[(pos<<1)+2];
// }

int main() {
    speedup;
    ll n;
    cin>>n;

    string com;
    cin>>com;

    ll pos = 0;
    vector<ll> txt(n);
    ll lstans=0;
    for (int i=0;i<n;i++) {
        ll val = 0;
        ll val2 = 0;
        if (com[i]=='(') {
            val2 = 1;
            if (txt[pos]==')')
                val=2;
            else if (txt[pos]=='(')
                val=0;
            else
                val=1;
            txt[pos]='(';
        }
        else if (com[i]==')') {
            val2 = -1;
            if (txt[pos]=='(')
                val=-2;
            else if (txt[pos]==')')
                val=0;
            else
                val=-1;
            txt[pos]=')';
        }
        else if (com[i]>='a' && com[i]<='z') {
            if (txt[pos]=='(')
                val=-1;
            else if (txt[pos]==')')
                val=+1;
            else
                val=0;
            txt[pos]=com[i];
        }
        else if (com[i]=='L') {
            pos = max(0ll,pos-1);
            cout<<lstans<<" ";
            continue;
        }
        else if (com[i]=='R') {
            pos = pos+1;
            cout<<lstans<<" ";
            continue;
        }

        if (val!=0)
            updateRange(pos,n-1,val,0,n-1,0);
        // updatePoint(pos,val2,0,n-1,0);

        if (queryMin(0,n-1,0,n-1,0)>=0 && queryMin(n-1,n-1,0,n-1,0)==0) {
            lstans = queryMax(0,n-1,0,n-1,0);
        } else {
            lstans = -1;
        }
        cout<<lstans<<" ";
    }
    cout<<endl;
    return 0;
}

/*
20
(R)R)R(R(RaR)R)R(R(R)
(   R   )   R   )   R   (   R   (   R   a   R   )   R   )   R   (   R   (   R   )
-1 -1   ?   ?   -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
())((a))(()
*/


#include <bits/stdc++.h>

// #include <boost/multiprecision/cpp_int.hpp>
// #define ll cpp_int
// using namespace boost::multiprecision;

using namespace std;
#define speedup ios::sync_with_stdio(0);cin.tie(0);
#define fileIO freopen("inp00.txt","r",stdin);freopen("out00.txt","w",stdout);
#define all(a) (a).begin(), (a).end()
#define ll long long
#define ld long double
#define pb push_back
#define mk make_pair
#define lb lower_bound
#define ub upper_bound
#define fi first
#define se second
#define INF INT_MAX
#define imi -1e18
#define ima 1e18
#define err(...) fprintf(stderr, _VA_ARGS_),fflush(stderr)
#define PI 3.14159265359
const ll mod = 1e9 + 7;

// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// #include <functional>
// using namespace __gnu_pbds;
// typedef tree<int, null_type, less<int>, rb_tree_tag,tree_order_statistics_node_update> pbds;

ll expo(ll a,ll b,ll m){if(a==0) return 1;ll res=1;while(b){if(b%2==1)res=((res%m)*(a%m))%m;a=((a%m)*(a%m))%m;b/=2;}return res%m;}
ld expo2(ld a,ll b){ld res=1;while(b){if(b%2==1)res=(res*a);a=(a*a);b/=2;}return res;}
ll mulmod(ll a,ll b,ll m){if(a==0) return 1;ll res=0;while(b){if(b%2==1)res=((res%m)+(a%m))%m;a=((a%m)+(a%m))%m;b/=2;}return res%m;}

ll gcd(ll a,ll b) {
    if (b==0)
        return a;
    return gcd(b,a%b);
}
#include <bits/stdc++.h>
using namespace std;

const ll N = 1000010;

ll seg1[N<<2];
ll seg2[N<<2];
// ll seg3[4*N];
ll lazy[N<<2];

// void buildTree(vector<ll> &seg,vector<ll> &arr,ll low, ll high, ll pos) {
//     if (low==high) {
//         seg[pos]=arr[low];
//         return;
//     }
//     ll mid = (low+high)/2;
//     buildTree(seg,arr,low,mid,pos<<1|1);
//     buildTree(seg,arr,mid+1,high,(pos<<1)+2);
//     seg[pos] = min(seg[pos<<1|1],seg[(pos<<1)+2]);
// }

ll queryMax(ll qlow,ll qhigh,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[pos<<1|1] += lazy[pos];
            lazy[(pos<<1)+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return 0;
    } else if (qlow<=low && qhigh>=high){
        return seg1[pos];
    }
    ll mid = (low+high)/2;
    ll left=queryMax(qlow,qhigh,low,mid,pos<<1|1);
    ll right=queryMax(qlow,qhigh,mid+1,high,(pos<<1)+2);
    return max(left,right);
}

ll queryMin(ll qlow,ll qhigh,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[pos<<1|1] += lazy[pos];
            lazy[(pos<<1)+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return INT_MAX;
    } else if (qlow<=low && qhigh>=high){
        return seg2[pos];
    }
    ll mid = (low+high)/2;
    ll left=queryMin(qlow,qhigh,low,mid,pos<<1|1);
    ll right=queryMin(qlow,qhigh,mid+1,high,(pos<<1)+2);
    return min(left,right);
}

void updateRange(ll qlow,ll qhigh,ll val,ll low, ll high,ll pos) {
    if (lazy[pos]!=0) {
        seg1[pos] += lazy[pos];
        seg2[pos] += lazy[pos];
        if (low!=high) {
            lazy[pos<<1|1] += lazy[pos];
            lazy[(pos<<1)+2] += lazy[pos];
        }
        lazy[pos] = 0;
    }

    if (qlow>high || qhigh<low) {
        return;
    } else if (qlow<=low && qhigh>=high){
        seg1[pos] += val;
        seg2[pos] += val;
        if (low!=high) {
            lazy[pos<<1|1] += val;
            lazy[(pos<<1)+2] += val;
        }
        return;
    } else {
        ll mid = (low+high)/2;
        updateRange(qlow,qhigh,val,low,mid,pos<<1|1);
        updateRange(qlow,qhigh,val,mid+1,high,(pos<<1)+2);
        seg1[pos] = max(seg1[pos<<1|1],seg1[(pos<<1)+2]);
        seg2[pos] = min(seg2[pos<<1|1],seg2[(pos<<1)+2]);
    }
}

// ll querySum(ll qlow, ll qhigh, ll low, ll high, ll pos) {
//     if (qhigh<low || qlow>high)
//         return 0;
//     if (qlow<=low && qhigh>=high)
//         return seg3[pos];
//     ll mid = (low+high)/2;
//     ll a1 = querySum(qlow,qhigh,low,mid,pos<<1|1);
//     ll a2 = querySum(qlow,qhigh,mid+1,high,(pos<<1)+2);
//     return a1+a2;
// }

// void updatePoint(ll index,ll val,ll low, ll high, ll pos) {
//     if (low>high)
//         return;
//     if (low==high) {
//         seg3[pos]=val;
//         return;
//     }
//     ll mid = (low+high)/2;
//     if (index<=mid)
//         updatePoint(index,val,low,mid,pos<<1|1);
//     else
//         updatePoint(index,val,mid+1,high,(pos<<1)+2);
//     seg3[pos] = seg3[pos<<1|1]+seg3[(pos<<1)+2];
// }

int main() {
    speedup;
    ll n;
    cin>>n;

    string com;
    cin>>com;

    ll pos = 0;
    vector<ll> txt(n);
    for (int i=0;i<n;i++) {
        ll val = 0;
        ll val2 = 0;
        if (com[i]=='(') {
            val2 = 1;
            if (txt[pos]==')')
                val=2;
            else if (txt[pos]=='(')
                val=0;
            else
                val=1;
            txt[pos]='(';
        }
        else if (com[i]==')') {
            val2 = -1;
            if (txt[pos]=='(')
                val=-2;
            else if (txt[pos]==')')
                val=0;
            else
                val=-1;
            txt[pos]=')';
        }
        else if (com[i]>='a' && com[i]<='z') {
            if (txt[pos]=='(')
                val=-1;
            else if (txt[pos]==')')
                val=+1;
            else
                val=0;
            txt[pos]=com[i];
        }
        else if (com[i]=='L')
            pos = max(0ll,pos-1);
        else if (com[i]=='R')
            pos = pos+1;

        if (val!=0)
            updateRange(pos,n-1,val,0,n-1,0);
        // updatePoint(pos,val2,0,n-1,0);

        if (queryMin(0,n-1,0,n-1,0)>=0 && queryMin(n-1,n-1,0,n-1,0)==0) {
            cout<<queryMax(0,n-1,0,n-1,0)<<" ";
        } else {
            cout<<"-1 ";
        }
    }
    cout<<endl;
    return 0;
}

/*
20
(R)R)R(R(RaR)R)R(R(R)
(   R   )   R   )   R   (   R   (   R   a   R   )   R   )   R   (   R   (   R   )
-1 -1   ?   ?   -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1  -1
())((a))(()
*/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define SPEED ios_base::sync_with_stdio(false); cin.tie(NULL);
#define FOR(i, a, b) for (ll i = a; i < b; ++i)
#define RFOR(i, b, a) for (ll i = b; i >= a; --i)
#define DEBUG(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' ');\
stringstream _ss(_s); istream_iterator<string> _it(_ss); _debug(_it, args);}
#define endl "\n"
#define F first
#define S second
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define mp(x, y) make_pair(x, y)

using namespace std;
using namespace __gnu_pbds;

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

void _debug(istream_iterator<string>) {}
template<typename T, typename... Args>
void _debug(istream_iterator<string> it, T first, Args... args) {
    cerr << ">> " << *it << " : " << first << endl; _debug(++it, args...);
}
template <typename T1, typename T2>
inline ostream& operator << (ostream& out, const pair<T1, T2>& p) {
    return out << "(" << p.F << ", " << p.S << ")";
}
template<typename T>
inline ostream& operator << (ostream& out, const vector<T>& v) {
    if (v.empty()) return out << "[]";
    else { out << '['; for (auto& e : v) { out << e << ", "; } return out << "\b\b]"; }
}
template<typename T>
inline ostream& operator << (ostream& out, const set<T>& s) {
    if (s.empty()) return out << "{}";
    else { out << '{'; for (auto& e : s) { out << e << ", "; } return out << "\b\b}"; }
}
template<typename T>
inline ostream& operator << (ostream& out, const unordered_set<T>& s) {
    return out << set<T>(ALL(s));
}
template<typename T1, typename T2>
inline ostream& operator << (ostream& out, const map<T1, T2>& m) {
    if (m.empty()) return out << "{}";
    out << '{'; for (auto& p : m) { out << p << ", "; } return out << "\b\b}";
}
template<typename T1, typename T2>
inline ostream& operator << (ostream& out, const unordered_map<T1, T2>& m) {
    return out << map<T1, T2>(ALL(m));
}
template<typename T>
inline ostream& operator << (ostream& out, const ordered_set<T>& s) {
    return out << set<T>(ALL(s));
}

typedef long long ll;
typedef long double ld;
typedef vector<long long> vll;
typedef pair<ll, ll> pll;
typedef vector<pair<ll, ll>> vpll;
typedef unordered_map<ll, ll> STll;
/************************************** MAIN PROGRAM ********************************************/

const int MAX = 1501;
char grid[MAX][MAX];
ll n, m;
bool marked[MAX][MAX];
int dR[] = {-1, 0, 0, 1};
int dC[] = {0, 1, -1, 0};

int fr(int x)
{
    if (x < 0)  x += MAX * n;

    return x % n;
}

int fc(int y)
{
    if (y < 0) y += MAX * m;

    return y % m;
}

set<pair<int, int>> st;

void dfs(int r, int c)
{
    //DEBUG(r, c)
    marked[fr(r)][fc(c)] = true;
    if (r == fr(r) && c == fc(c))
        st.insert(mp(fr(r), fc(c)));
    //if (st.size() >= n * m) {
    //    cout << "YES";
  //      exit(0);
//    }

    for (int k = 0; k < 4; ++k)
    {
        int x = r + dR[k];
        int y = c + dC[k];

        if (grid[fr(x)][fc(y)] == '#') continue;

        if (!marked[fr(x)][fc(y)])
            dfs(x, y);
        else {
            if (x == fr(x) && y == fc(y))
                continue;
            else {
                    DEBUG(r, c, x, y, fr(x), fc(y))
                cout << "YES";
                exit(0);
            }
        }

    }
}

int main()
{
    //freopen("input.txt", "r", stdin);
    SPEED

    cin >> n >> m;
    FOR(i, 0, n)
    {
        cin >> grid[i];
    }
    FOR(i, 0, n)
    {
        FOR(j, 0, n)
        {
            if (grid[i][j] == 'S')
            {
                dfs(i, j);
            }
        }
    }
    cout << "NO";
}
/************************************** END OF PROGRAM ******************************************/


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define SPEED ios_base::sync_with_stdio(false); cin.tie(NULL);
#define FOR(i, a, b) for (ll i = a; i < b; ++i)
#define RFOR(i, b, a) for (ll i = b; i >= a; --i)
#define DEBUG(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' ');\
stringstream _ss(_s); istream_iterator<string> _it(_ss); _debug(_it, args);}
#define endl "\n"
#define F first
#define S second
#define pb(x) push_back(x)
#define ALL(x) x.begin(), x.end()
#define mp(x, y) make_pair(x, y)

using namespace std;
using namespace __gnu_pbds;

template<typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

void _debug(istream_iterator<string>) {}
template<typename T, typename... Args>
void _debug(istream_iterator<string> it, T first, Args... args) {
    cerr << ">> " << *it << " : " << first << endl; _debug(++it, args...);
}
template <typename T1, typename T2>
inline ostream& operator << (ostream& out, const pair<T1, T2>& p) {
    return out << "(" << p.F << ", " << p.S << ")";
}
template<typename T>
inline ostream& operator << (ostream& out, const vector<T>& v) {
    if (v.empty()) return out << "[]";
    else { out << '['; for (auto& e : v) { out << e << ", "; } return out << "\b\b]"; }
}
template<typename T>
inline ostream& operator << (ostream& out, const set<T>& s) {
    if (s.empty()) return out << "{}";
    else { out << '{'; for (auto& e : s) { out << e << ", "; } return out << "\b\b}"; }
}
template<typename T>
inline ostream& operator << (ostream& out, const unordered_set<T>& s) {
    return out << set<T>(ALL(s));
}
template<typename T1, typename T2>
inline ostream& operator << (ostream& out, const map<T1, T2>& m) {
    if (m.empty()) return out << "{}";
    out << '{'; for (auto& p : m) { out << p << ", "; } return out << "\b\b}";
}
template<typename T1, typename T2>
inline ostream& operator << (ostream& out, const unordered_map<T1, T2>& m) {
    return out << map<T1, T2>(ALL(m));
}
template<typename T>
inline ostream& operator << (ostream& out, const ordered_set<T>& s) {
    return out << set<T>(ALL(s));
}

typedef long long ll;
typedef long double ld;
typedef vector<long long> vll;
typedef pair<ll, ll> pll;
typedef vector<pair<ll, ll>> vpll;
typedef unordered_map<ll, ll> STll;
/************************************** MAIN PROGRAM ********************************************/

const int MAX = 1501;
char grid[MAX][MAX];
ll n, m;
bool marked[MAX][MAX];
int dR[] = {-1, 0, 0, 1};
int dC[] = {0, 1, -1, 0};

int fr(int x)
{
    if (x < 0)  x += MAX * n;

    return x % n;
}

int fc(int y)
{
    if (y < 0) y += MAX * m;

    return y % m;
}

set<pair<int, int>> st;

void dfs(int r, int c)
{
    //DEBUG(r, c)
    marked[fr(r)][fc(c)] = true;
    if (r == fr(r) && c == fc(c))
        st.insert(mp(fr(r), fc(c)));
    if (st.size() >= n * m) {
        cout << "YES";
       exit(0);
    }

    for (int k = 0; k < 4; ++k)
    {
        int x = r + dR[k];
        int y = c + dC[k];

        if (grid[fr(x)][fc(y)] == '#') continue;

        if (!marked[fr(x)][fc(y)])
            dfs(x, y);
        else {
            if (x == fr(x) && y == fc(y))
                continue;
            else {
                   // DEBUG(r, c, x, y, fr(x), fc(y))
                cout << "YES";
                exit(0);
            }
        }

    }
}

int main()
{
    //freopen("input.txt", "r", stdin);
    SPEED

    cin >> n >> m;
    FOR(i, 0, n)
    {
        cin >> grid[i];
    }
    FOR(i, 0, n)
    {
        FOR(j, 0, n)
        {
            if (grid[i][j] == 'S')
            {
                dfs(i, j);
            }
        }
    }

    cout << "NO";
}
/************************************** END OF PROGRAM ******************************************/


#include<cstdio>
#include<iostream>
using namespace std;
int n,m,flag,fl;
char map[2000][2000],b[3][3][2000][2000];
int dfs(int x,int y,int xx,int yy){
    if(x==0) x=n,xx--;
    if(y==0) y=m,yy--;
    if(x==n+1) x=1,xx++;
    if(y==m+1) y=1,yy++;
    if(xx<0||yy<0||xx>2||yy>2) return 0;
    //if(b[x][y]&&flag) fl=1;
    if(b[xx][yy][x][y]) return 0;
    if(map[x][y]=='#') return 0;
    b[xx][yy][x][y]=1;
    dfs(x+1,y,xx,yy);
    dfs(x-1,y,xx,yy);
    dfs(x,y+1,xx,yy);
    dfs(x,y-1,xx,yy);
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%s",map[i]+1);
    for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	    if(map[i][j]=='S')
		dfs(i,j,1,1);
    for(int i=1;i<=n;i++)
	for(int j=1;j<=m;j++)
	    if(map[i][j]=='S')
	    for(int ii=0;ii<3;ii++)
		for(int jj=0;jj<3;jj++)
		    if(!((ii==1)&&(jj==1)))
			if(b[ii][jj][i][j])
			    return printf("Yes"),0;
			    /*
	    for(int ii=0;ii<3;ii++)
		for(int jj=0;jj<3;jj++,printf("\n"))
    for(int i=1;i<=n;i++,printf("\n"))
	for(int j=1;j<=m;j++)
	    printf("%d",b[ii][jj][i][j]);
    for(int i=1;i<=n;i++)
	if(b[i][1]&&b[i][m])
	    return printf("Yes"),0;
    for(int i=1;i<=m;i++)
	if(b[1][i]&&b[n][i])
	    return printf("Yes"),0;
    */
    printf("No");
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define endl '\n'
#define clr(v,val) memset(v,val,sizeof(v))
#define sz(v) (int)(v.size())
#define all(v) v.begin(),v.end()
#define allr(v) v.rbegin(),v.rend()
#define RT(v,val) return cout<<v,val
#define watch(x) cout << (#x) << " = " << x << endl
#define oo INT_MAX
int dr[]{ 1, -1, 0, 0, 1, 1, -1, -1 };
int dc[]{ 0, 0, 1, -1, 1, -1, 1, -1 };

void run() {
	ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#ifndef ONLINE_JUDGE
	auto it = freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
}
int n, m;
const int N = 1510;
char arr[N][N];
bool vis[N][N];
bool ans[N][N];
int fixMod(int a, int b) { return (a % b + b) % b; }

bool dfs(int i, int j, int cnt = 0) {
	vis[i][j] = true;
	bool& b = ans[i][j];
	for (int k = 0; k < 4; k++) {
		int x = fixMod(i + dr[k], n),
			y = fixMod(j + dc[k], m);
		if (arr[x][y] == '.') {
			if (!vis[x][y])
				b |= dfs(x, y, cnt + 1);
		}
		else if (arr[x][y] == 'S') {
			if (cnt > 1) {
				b = true;
				return b;
			}
		}
	}
	return b;
}

int main() {
	run();
	cin >> n >> m;
	int x = 0, y = 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 'S')
				x = i, y = j;
		}
	dfs(x, y);
	if (ans[x][y])
		cout << "Yes";
	else cout << "No";
}


#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define endl '\n'
#define clr(v,val) memset(v,val,sizeof(v))
#define sz(v) (int)(v.size())
#define all(v) v.begin(),v.end()
#define allr(v) v.rbegin(),v.rend()
#define RT(v,val) return cout<<v,val
#define watch(x) cout << (#x) << " = " << x << endl
#define oo INT_MAX
int dr[]{ 1, -1, 0, 0, 1, 1, -1, -1 };
int dc[]{ 0, 0, 1, -1, 1, -1, 1, -1 };

void run() {
	ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#ifndef ONLINE_JUDGE
	auto it = freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
}
int n, m;
const int N = 1510;
char arr[N][N];
int ans[N][N];
int fixMod(int a, int b) { return (a % b + b) % b; }

bool dfs(int i, int j,bool out = false,bool s = true) {
	int& b = ans[i][j];
	if (s && arr[i][j] == 'S') {
		b = out;
		return b;
	}
	if (b != -1)return b;
	b = 0;
	for (int k = 0; k < 4; k++) {
		int x = i + dr[k],
			y = j + dc[k];
		if (x < 0 || x >= n || y < 0 || y >= m) {
			x = fixMod(x, n), y = fixMod(y, m);
			if (arr[x][y] == '.' || arr[x][y] == 'S')
				b |= dfs(x, y, true);
		}
		else if (arr[x][y] == '.' || arr[x][y] == 'S') {
			b |= dfs(x, y, out);
		}
	}
	return b;
}

int main() {
	run();
	clr(ans, -1);
	cin >> n >> m;
	int x = 0, y = 0;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 'S')
				x = i, y = j;
		}
	dfs(x, y, false, false);
	if (ans[x][y] == 1)
		cout << "Yes";
	else cout << "No";
}


#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define endl '\n'
#define clr(v,val) memset(v,val,sizeof(v))
#define sz(v) (int)(v.size())
#define all(v) v.begin(),v.end()
#define RT(v) return cout<<v,0
#define watch(x) cout<<(#x)<<" = "<<x<<endl
const int oo = INT_MAX, mod = 1e9 + 7;
const double PI = acos(-1), EPS = 1e-5;
int dr[]{ -1, 1, 0, 0, 1, 1, -1, -1 };
int dc[]{ 0, 0, 1, -1, 1, -1, 1, -1 };
void run() {
	ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
}
typedef pair<int, int> pii;
map<pii, pii> mp;
char arr[1510][1510];
int fixMod(int a, int b) { return (a % b + b) % b; }

int n, m;
bool dfs(int i, int j) {
	int x = fixMod(i, n), y = fixMod(j, m);
	if (arr[x][y] == '#')return false;
	if (mp.find({ x,y }) != mp.end()) {
		pii p = mp[{x, y}];
		if (p.first == i && p.second == j)
			return false;
		return true;
	}
	mp[{x, y}] = { i,j };
	bool b = 0;
	for (int k = 0; k < 4; k++) {
		x = i + dr[k], y = j + dc[k];
		b |= dfs(x, y);
	}
	return b;
}

int main() {
	run();
	cin >> n >> m;
	pii s;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++){
			cin >> arr[i][j];
			if (arr[i][j] == 'S')
				s = { i,j };
		}
	bool b = dfs(s.first, s.second);
	cout << (b ? "Yes": "No");

}


#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define endl '\n'
#define clr(v,val) memset(v,val,sizeof(v))
#define sz(v) (int)(v.size())
#define all(v) v.begin(),v.end()
#define RT(v) return cout<<v,0
#define watch(x) cout<<(#x)<<" = "<<x<<endl
const int oo = INT_MAX, mod = 1e9 + 7;
const double PI = acos(-1), EPS = 1e-5;
int dr[]{ -1, 1, 0, 0, 1, 1, -1, -1 };
int dc[]{ 0, 0, 1, -1, 1, -1, 1, -1 };
void run() {
	ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
	//freopen("output.out", "w", stdout);
#endif
}
pair<int, int> OO = { oo,oo }, s;
pair<int, int> ans[1510][1510] = { OO };
int fixMod(int a, int b) { return (a % b + b) % b; }
int n, m;
char arr[1510][1510];
bool dfs(int i, int j) {
	int x = fixMod(i, n), y = fixMod(j, m);
	if (arr[x][y] == '#')return false;
	if (ans[x][y] != OO) {
		pair<int,int> p = ans[x][y];
		if (p.first == i && p.second == j)
			return false;
		return true;
	}
	ans[x][y] = { i,j };
	bool b = 0;
	for (int k = 0; k < 4; k++) {
		x = i + dr[k], y = j + dc[k];
		b |= dfs(x, y);
	}
	return b;
}

int main() {
	run();
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			cin >> arr[i][j];
			if (arr[i][j] == 'S')
				s = { i,j };
		}
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			ans[i][j] = OO;
	bool b = dfs(s.first, s.second);
	cout << (b ? "Yes": "No");
}


	#include<bits/stdc++.h>
	#include <ext/pb_ds/assoc_container.hpp>
	using namespace __gnu_pbds;
	using namespace std;

	#define fi              first
	#define se              second
	#define ll              long long
	#define pb              push_back
	#define mp              make_pair
	#define pii             pair<int,int>
	#define vi              vector<int>
	#define mii             map<int,int>
	#define pqb             priority_queue<int>
	#define pqs             priority_queue<int,vi,greater<int> >
	#define setbits(x)      __builtin_popcountll(x)
	#define zrobits(x)      __builtin_ctzll(x)
	#define mod             1000000007
	#define inf             1e18
	#define ps(x,y)         fixed<<setprecision(y)<<x
	#define mk(arr,n,type)  type *arr=new type[n];
	#define w(x)            int x; cin>>x; while(x--)
	#define FIO             ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
	mt19937                 rng(chrono::steady_clock::now().time_since_epoch().count());

	typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;

	const int N=2e5+5;

	ll n,m;

	pair<ll,ll> vis[1505][1505];

	vector<string> v(1505);

	ll dx[]={-1,0,1,0};
	ll dy[]={0,1,0,-1};

	void dfs(ll x,ll y)
	{
		//cout<<x<<" "<<y<<endl;
		pair<ll,ll> p1={x,y};

		ll x1=((x%n)+n)%n;
		ll y1=((y%m)+m)%m;

		if(vis[x1][y1]==p1)
		{
			return;
		}
		pair<ll,ll> p={inf,inf};
		if(vis[x1][y1]!=p)
		{
			//cout<<vis[x1][y1].fi<<" "<<vis[x1][y1].se<<" "<<x<<" "<<y<<endl;
			cout<<"Yes";
			exit(0);
		}
		vis[x1][y1]=p1;

		for(ll i=0;i<4;i++)
		{
			x1=x+dx[i];
			y1=y+dy[i];
			x1=((x1%n)+n)%n;
			y1=((y1%m)+m)%m;

			if(v[x1][y1]!='#')
			{
				dfs(x+dx[i],y+dy[i]);
			}
		}
	}

	int main()
	{
		 FIO;

		 cin>>n>>m;

		 ll posx=-1,posy=-1;
		 for(ll i=0;i<n;i++)
		 {
			 cin>>v[i];
		 }

		 for(ll i=0;i<n;i++)
		 {
			 for(ll j=0;j<m;j++)
			 {
				 if(v[i][j]=='S')
				 {
					 posx=i;
					 posy=j;
				 }
				 vis[i][j]={inf,inf};

			 }
		 }

		 dfs(posx,posy);
		 cout<<"No";

	}


	#include<bits/stdc++.h>
	#include <ext/pb_ds/assoc_container.hpp>
	using namespace __gnu_pbds;
	using namespace std;

	#define fi              first
	#define se              second
	#define ll              long long
	#define pb              push_back
	#define mp              make_pair
	#define pii             pair<int,int>
	#define vi              vector<int>
	#define mii             map<int,int>
	#define pqb             priority_queue<int>
	#define pqs             priority_queue<int,vi,greater<int> >
	#define setbits(x)      __builtin_popcountll(x)
	#define zrobits(x)      __builtin_ctzll(x)
	#define mod             1000000007
	#define inf             1e9
	#define ps(x,y)         fixed<<setprecision(y)<<x
	#define mk(arr,n,type)  type *arr=new type[n];
	#define w(x)            int x; cin>>x; while(x--)
	#define FIO             ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
	mt19937                 rng(chrono::steady_clock::now().time_since_epoch().count());

	typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;

	const int N=2e5+5;

	int n,m;

	pair<int,int> vis[1505][1505];

	vector<string> v(1505);

	int dx[]={-1,0,1,0};
	int dy[]={0,1,0,-1};

	void dfs(int x,int y)
	{
		//cout<<x<<" "<<y<<endl;
		pair<int,int> p1={x,y};

		ll x1=((x%n)+n)%n;
		ll y1=((y%m)+m)%m;

		if(vis[x1][y1]==p1)
		{
			return;
		}
		pair<int,int> p={inf,inf};
		if(vis[x1][y1]!=p)
		{
			//cout<<vis[x1][y1].fi<<" "<<vis[x1][y1].se<<" "<<x<<" "<<y<<endl;
			cout<<"Yes";
			exit(0);
		}
		vis[x1][y1]=p1;

		for(ll i=0;i<4;i++)
		{
			x1=x+dx[i];
			y1=y+dy[i];
			x1=((x1%n)+n)%n;
			y1=((y1%m)+m)%m;

			if(v[x1][y1]!='#')
			{
				dfs(x+dx[i],y+dy[i]);
			}
		}
	}

	int main()
	{
		 FIO;

		 cin>>n>>m;

		 int posx=-1,posy=-1;
		 for(int i=0;i<n;i++)
		 {
			 cin>>v[i];
		 }

		 for(int i=0;i<n;i++)
		 {
			 for(int j=0;j<m;j++)
			 {
				 if(v[i][j]=='S')
				 {
					 posx=i;
					 posy=j;
				 }
				 vis[i][j]={inf,inf};

			 }
		 }

		 dfs(posx,posy);
		 cout<<"No";

	}


    #include <bits/stdc++.h>

    using namespace std;
    #define ll long long
    string arr[1505];
    int vis[1505][1505];
    int check=0;
    int dx[]={0,0,1,-1};
    int dy[]={1,-1,0,0};
    int n,m;
    int b=1;
    pair<ll,ll> mark[1505][1505];
    void DFS(int i,int j,int prex,int prey,int realx,int realy){
        if(arr[i][j]=='#') return ;
        if(vis[i][j]==1){
            if((mark[i][j].first!=realx || mark[i][j].second!=realy)&& b==1 ){
                check=1;
                b=0;
            }
            return;
        }

        vis[i][j]=1;
        mark[i][j]={realx,realy};
        for(int k=0;k<4;k++){
            int x=(realx+dx[k]),y=realy+dy[k];
            DFS((x%n+n)%n,(y%m+m)%m,i,j,x,y);
        }
    }
    int main()
    {
         cin>>n>>m;
        for(int i=0;i<n;i++) cin>>arr[i];
        int startx=-1,starty=-1;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(arr[i][j]=='S') startx=i,starty=j;
            }
        }
        DFS(startx,starty,-1,-1,startx,starty);
        if(check){
            cout<<"Yes";
        }else cout<<"No";
        return 0;
    }


#include <bits/stdc++.h>

using namespace std;

string arr[1505];
int vis[1505][1505];
int check=0;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int n,m;
int b=1;
void DFS(int i,int j,int prex,int prey,int realx,int realy){
    if(arr[i][j]=='#') return ;
  //  cout<<i<<" "<<j<<endl;
   // cout<<realx<<" "<<realy<<endl;
    if(vis[i][j]==1){
        if((realx!=i || realy!=j)&& b==1 ){
            check=1;
            b=0;
        }
        b=0;
        return;
    }

    vis[i][j]=1;
    for(int k=0;k<4;k++){
        int x=(realx+dx[k]),y=realy+dy[k];
        if((x+n)%n!=prex || prey!=(y+m)%m)
        DFS((x+n)%n,(y+m)%m,i,j,x,y);
    }
}
int main()
{
     cin>>n>>m;
    for(int i=0;i<n;i++) cin>>arr[i];
    int startx=-1,starty=-1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(arr[i][j]=='S') startx=i,starty=j;
        }
    }
    DFS(startx,starty,-1,-1,startx,starty);
    if(check){
        cout<<"Yes";
    }else cout<<"No";
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ll long long
vector<string> v;
bool valide=0;
int vis[1505][1505];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
ll n,m;
bool valid(int e,int r){
    return e>=0 && r>=0 && r<v[0].size() && e<v.size();
}
void DFS(int i,int j){
    if(v[i][j]=='E') {
        valide=1;
        return;
    }
    vis[i][j]=1;
    for(int k=0;k<4;k++){
        int x=i+dx[k],y=j+dy[k];
        if(!vis[x][y] && valid(x,y) && v[x][y]!='#'){
            DFS(x,y);
        }
    }
}
int main()
{
   cin>>n>>m;
    for(int i=0;i<n;i++){
        string s; cin>>s;
        v.push_back(s);
    }
    for(int i=0;i<n;i++){
        v.push_back(v[i]);
    }

    int f=0;
    for(int i=0;i<v.size();i++){
        for(int j=0;j<v[i].size();j++){
            if(v[i][j]=='S'){ v[i][j]='E'; f=1; break; }
        }
        if(f==1) break;
    }
    f=0;
    int x=-1,y=-1;
    for(int i=0;i<v.size();i++){
        for(int j=0;j<v[i].size();j++){
            if(v[i][j]=='S'){ x=i,y=j,f=1; break; }
        }
        if(f==1) break;
    }
    DFS(x,y);
    if(valide){
        cout<<"Yes";
    }
    else cout<<"No";
    return 0;
}


    #include <bits/stdc++.h>

    using namespace std;
    #define ll long long
    string arr[1505];
    int vis[1505][1505];
    int check=0;
    int dx[]={0,0,1,-1};
    int dy[]={1,-1,0,0};
    int n,m;
    int b=1;
    pair<ll,ll> mark[1505][1505];
    void DFS(int i,int j,int prex,int prey,int realx,int realy){
        if(arr[i][j]=='#') return ;
        if(vis[i][j]==1){
            if((mark[i][j].first!=realx || mark[i][j].second!=realy)&& b==1 ){
                check=1;
            }
            b=0;
            return;
        }

        vis[i][j]=1;
        mark[i][j]={realx,realy};
        for(int k=0;k<4;k++){
            int x=(realx+dx[k]),y=realy+dy[k];
            if((x%n+n)%n!=prex || prey!=(y%m+m)%m)
            DFS((x%n+n)%n,(y%m+m)%m,i,j,x,y);
        }
    }
    int main()
    {
         cin>>n>>m;
        for(int i=0;i<n;i++) cin>>arr[i];
        int startx=-1,starty=-1;
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(arr[i][j]=='S') startx=i,starty=j;
            }
        }
        DFS(startx,starty,-1,-1,startx,starty);
        if(check){
            cout<<"Yes";
        }else cout<<"No";
        return 0;
    }


#include <bits/stdc++.h>

using namespace std;

string arr[1505];
int vis[1505][1505];
int check=0;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int n,m;
void DFS(int i,int j,int prex,int prey,int realx,int realy){
    if(arr[i][j]=='#') return ;
    if(vis[i][j]==1){
        if(realx!=i || realy!=j){
            check=1;
        }
        return;
    }

    vis[i][j]=1;
    for(int k=0;k<4;k++){
        int x=(realx+dx[k]),y=realy+dy[k];
        if((x+n)%n!=prex || prey!=(y+m)%m)
        DFS((x+n)%n,(y+m)%m,i,j,x,y);
    }
}
int main()
{
     cin>>n>>m;
    for(int i=0;i<n;i++) cin>>arr[i];
    int startx=-1,starty=-1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(arr[i][j]=='S') startx=i,starty=j;
        }
    }
    DFS(startx,starty,-1,-1,startx,starty);
    if(check){
        cout<<"Yes";
    }else cout<<"No";
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

string arr[1505];
int vis[1505][1505];
int check=0;
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
int n,m;
int b=1;
void DFS(int i,int j,int prex,int prey,int realx,int realy){
    if(arr[i][j]=='#') return ;
  //  cout<<i<<" "<<j<<endl;
   // cout<<realx<<" "<<realy<<endl;
    if(vis[i][j]==1){
        if((realx!=i || realy!=j)&& b==1 ){
            check=1;
            b=0;
        }
        b=0;
        return;
    }

    vis[i][j]=1;
    for(int k=0;k<4;k++){
        int x=(realx+dx[k]),y=realy+dy[k];
        if((x%n+n)%n!=prex || prey!=(y%m+m)%m)
        DFS((x%n+n)%n,(y%m+m)%m,i,j,x,y);
    }
}
int main()
{
     cin>>n>>m;
    for(int i=0;i<n;i++) cin>>arr[i];
    int startx=-1,starty=-1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(arr[i][j]=='S') startx=i,starty=j;
        }
    }
    DFS(startx,starty,-1,-1,startx,starty);
    if(check){
        cout<<"Yes";
    }else cout<<"No";
    return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
using namespace std;
void fast()
{
	std::ios_base::sync_with_stdio(0);
	cin.tie(NULL); cout.tie(NULL);
}
int n, m, si, sj;
vector<vector<int>> v;
map<pair<int, int>, int > mp;
int vis[2000][2000];
char a[2000][2000];
bool b = 0;

void dfs(int i,int j)
{
	if ( b ) return;
	int ii, jj;
	ii = i, jj = j;

	while (i < 0) i += n;
	while (j < 0) j += m;
	if (i >= n) i %= n;
	if (j >= m) j %= m;

	if ( vis[i][j] && mp[{ii, jj}] == 0)
	{
		b = 1;
		return;
	}
	if (vis[i][j] || a[i][j] == '#') return;

	//cout << ii << " " << jj << " " << i << " " << j << "  " << b << endl;

	vis[i][j] = 1;
	mp[{ii, jj}] = 1;

	dfs(ii, jj + 1);
	dfs(ii, jj - 1);
	dfs(ii + 1, jj);
	dfs(ii - 1, jj);
}
int  main()
{
	fast();
	cin >> n >> m;
	for (int i = 0;i < n;i++)
		for (int j = 0;j < m;j++)
		{
			cin >> a[i][j];
			if (a[i][j] == 'S') si = i, sj = j;
		}
	v.resize(n + 2);
	mp[{si, sj}] = 1;
	dfs(si, sj);
	if (b) cout << "Yes" << endl;
	else cout << "No" << endl;
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
}
template<typename T, typename l>
void getv(T& a, int n, l f) {
	a.resize(n);
	for (auto& i : a)
		cin >> i, f(i);
}
template<typename T>
void getv(T& a, int n) {
	a.resize(n);
	for (auto& i : a)
		cin >> i;
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
int n, m, sx, sy, dx[] = { 1, -1, 0, 0 }, dy[] = { 0, 0, 1, -1 };
char mat[12100][12100];
const int bias = 5011;
//mat[(n+x)%n][(m+y)%m]
void dfs(int x, int y) {
	if (mat[x][y] == 'V')
		return;
	else
		mat[x][y] = mat[bias + (10*n+x-bias)%n][bias + (10*m+y-bias)%m];
	if (mat[x][y] == '#')
		return;
	if (((x-bias) > 2*n || (y-bias) >= 2*m) || ((x-bias) < -2*n || (y-bias) < -2*m)) {
		cout << "Yes";
		exit(0);
	}
	mat[x][y] = 'V';
	for (int i = 0; i < 4; i++)
		dfs(x + dx[i], y + dy[i]);

}

int main() {
	doin();
	cin >> n >> m;
	for (int i = bias; i < bias+n; i++)
		for (int j = bias; j < bias+m; j++) {
			cin >> mat[i][j];
			if (mat[i][j] == 'S')
				sx = i, sy = j;
		}
	dfs(sx, sy);
	cout << "No";
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
}
template<typename T, typename l>
void getv(T& a, int n, l f) {
	a.resize(n);
	for (auto& i : a)
		cin >> i, f(i);
}
template<typename T>
void getv(T& a, int n) {
	a.resize(n);
	for (auto& i : a)
		cin >> i;
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
int n, m, sx, sy, dx[] = { 1, -1, 0, 0 }, dy[] = { 0, 0, 1, -1 };
char mat[8010][8010];
const int bias = 4001;
//mat[(n+x)%n][(m+y)%m]
void dfs(int x, int y) {
	if (mat[x][y] == 'V')
		return;
	else
		mat[x][y] = mat[bias + (5*n+x-bias)%n][bias + (5*m+y-bias)%m];
	if (mat[x][y] == '#')
		return;
	if (x > sx+2*n || y > sy+2*m || x < sx-2*n || y < sy-2*m) {
		cout << "Yes";
		exit(0);
	}
	mat[x][y] = 'V';
	for (int i = 0; i < 4; i++)
		dfs(x + dx[i], y + dy[i]);

}

int main() {
	doin();
	cin >> n >> m;
	for (int i = bias; i < bias+n; i++)
		for (int j = bias; j < bias+m; j++) {
			cin >> mat[i][j];
			if (mat[i][j] == 'S')
				sx = i, sy = j;
		}
	dfs(sx, sy);
	cout << "No";
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
}
template<typename T, typename l>
void getv(T& a, int n, l f) {
	a.resize(n);
	for (auto& i : a)
		cin >> i, f(i);
}
template<typename T>
void getv(T& a, int n) {
	a.resize(n);
	for (auto& i : a)
		cin >> i;
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
int n, m, sx, sy, dx[] = { 1, -1, 0, 0 }, dy[] = { 0, 0, 1, -1 }, a = 0;
char mat[5001][5001];
pi vis[5000][5000];
set<pi> fk;
const int bias = 2000;
//mat[(n+x)%n][(m+y)%m]
void dfs(int x, int y) {
	if (mat[(100 * n + x) % n][(100 * m + y) % m] == 'V'
			&& vis[(100 * n + x) % n][(100 * m + y) % m] != pi(x, y)
			) {
		cout << "Yes";
		exit(0);
	}
	if (mat[(100 * n + x) % n][(100 * m + y) % m] == '#' || mat[(100 * n + x) % n][(100 * m + y) % m] == 'V')
		return;
	vis[(100 * n + x) % n][(100 * m + y) % m] = pi(x, y);
	mat[(100 * n + x) % n][(100 * m + y) % m] = 'V';
	for (int i = 0; i < 4; i++)
		dfs(x + dx[i], y + dy[i]);

}

int main() {
	doin();
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++) {
			cin >> mat[i][j];
			if (mat[i][j] == 'S')
				sx = i, sy = j;
		}
	dfs(sx, sy);
	cout << "No";
}


#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first.first
#define yy first.second
#define __V vector
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define oit ostream_iterator
#define mod 1000000007ll
using namespace __gnu_pbds;
using namespace std;
void doin() {
	cin.tie();
	cout.tie();
	ios::sync_with_stdio(0);
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
}
template<typename T, typename l>
void getv(T& a, int n, l f) {
	a.resize(n);
	for (auto& i : a)
		cin >> i, f(i);
}
template<typename T>
void getv(T& a, int n) {
	a.resize(n);
	for (auto& i : a)
		cin >> i;
}
typedef unsigned long long ull;
typedef long long ll;
typedef double ld;
typedef ll _I;
typedef pair<_I, _I> pi;
typedef pair<ld, ld> pd;
typedef map<_I, _I> mii;
typedef __V <_I> vi;
typedef __V <char> vc;
typedef __V <ld> vd;
typedef __V <vd> vvd;
typedef __V <pi> vpi;
typedef __V <__V<_I>> vvi;
typedef __V <__V<char>> vvc;
typedef __V <__V<pi>> vvpi;
int n, m, sx, sy, dx[] = { 1, -1, 0, 0 }, dy[] = { 0, 0, 1, -1 };
char mat[12010][12010];
const int bias = 6001;
//mat[(n+x)%n][(m+y)%m]
void dfs(int x, int y) {
	if (mat[x][y] == 'V')
		return;
	else
		mat[x][y] = mat[bias + (5*n+x-bias)%n][bias + (5*m+y-bias)%m];
	if (mat[x][y] == '#')
		return;
	if (x > sx+2*n || y > sy+2*m || x < sx-2*n || y < sy-2*m) {
		cout << "Yes";
		exit(0);
	}
	mat[x][y] = 'V';
	for (int i = 0; i < 4; i++)
		dfs(x + dx[i], y + dy[i]);

}

int main() {
	doin();
	cin >> n >> m;
	for (int i = bias; i < bias+n; i++)
		for (int j = bias; j < bias+m; j++) {
			cin >> mat[i][j];
			if (mat[i][j] == 'S')
				sx = i, sy = j;
		}
	dfs(sx, sy);
	cout << "No";
}