#include using namespace std; #ifndef LOCAL #define dbg(...) void() #define debug() if (false) #else namespace dbg::options { template<> constexpr bool trivial_string() { return true; } } // namespace dbg::options #endif template struct y_comb_t { F f; template y_comb_t(T &&_f) : f(forward(_f)) {} template decltype(auto) operator()(Args &&...args) { return f(/* ref */(*this), forward(args)...); } }; template y_comb_t> y_comb(F &&f) { return {forward(f)}; } void solve() { int n, q; string s; cin >> n >> q >> s; int m = n / 2; stack st; vector> g(m + 1); vector lab(n + 1, m); vector> bounds(m); int id = 0; st.push(n); for (int i = 0; i < n; i++) { if (s[i] == '(') { st.push(i); lab[i] = id++; } else { int other = st.top(); st.pop(); lab[i] = lab[other]; bounds[lab[i]] = {other + 1, i + 1}; g[lab[st.top()]] += lab[i]; } } int time = 0; vector in(m + 1), out(m + 1); const int L = __lg(m) + 1; vector up(L, vector(m + 1, -1)); y_comb([&](auto &dfs, int v, int p = -1) -> void { up[0][v] = p; for (int l = 0; l + 1 < L && up[l][v] != -1; l++) up[l + 1][v] = up[l][up[l][v]]; in[v] = time++; for (int c : g[v]) { dfs(c, v); } out[v] = time; })(m); auto anc = [&](int p, int v) { return p == -1 || (in[p] <= in[v] && out[v] <= out[p]); }; auto lca = [&](int u, int v) { if (anc(u, v)) return u; if (anc(v, u)) return v; for (int l = L - 1; l >= 0; l--) if (!anc(up[l][u], v)) u = up[l][u]; return up[0][u]; }; while (q--) { int x, y; cin >> x >> y, x--, y--; id = lca(lab[x], lab[y]); if (id == m) { cout << "-1\n"; continue; } auto [l, r] = bounds[id]; cout << l << " " << r << "\n"; } } int main() { cin.tie(0)->sync_with_stdio(0); solve(); }