結果

問題 No.1778 括弧列クエリ / Bracketed Sequence Query
ユーザー miscalcmiscalc
提出日時 2023-12-04 21:34:05
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 661 ms / 2,000 ms
コード長 6,438 bytes
コンパイル時間 5,601 ms
コンパイル使用メモリ 282,760 KB
実行使用メモリ 22,128 KB
最終ジャッジ日時 2023-12-04 21:34:27
合計ジャッジ時間 21,847 ms
ジャッジサーバーID
(参考情報)
judge11 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 374 ms
6,676 KB
testcase_01 AC 383 ms
6,676 KB
testcase_02 AC 371 ms
6,676 KB
testcase_03 AC 382 ms
6,676 KB
testcase_04 AC 376 ms
6,676 KB
testcase_05 AC 276 ms
10,752 KB
testcase_06 AC 175 ms
6,676 KB
testcase_07 AC 13 ms
7,040 KB
testcase_08 AC 560 ms
21,632 KB
testcase_09 AC 55 ms
9,600 KB
testcase_10 AC 232 ms
17,152 KB
testcase_11 AC 201 ms
12,672 KB
testcase_12 AC 292 ms
10,752 KB
testcase_13 AC 517 ms
21,120 KB
testcase_14 AC 199 ms
15,744 KB
testcase_15 AC 2 ms
6,676 KB
testcase_16 AC 567 ms
21,632 KB
testcase_17 AC 536 ms
21,632 KB
testcase_18 AC 570 ms
21,632 KB
testcase_19 AC 542 ms
21,632 KB
testcase_20 AC 545 ms
21,632 KB
testcase_21 AC 2 ms
6,676 KB
testcase_22 AC 2 ms
6,676 KB
testcase_23 AC 506 ms
18,212 KB
testcase_24 AC 538 ms
22,128 KB
testcase_25 AC 562 ms
22,128 KB
testcase_26 AC 661 ms
21,248 KB
testcase_27 AC 412 ms
21,248 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using pll = pair<ll, ll>;
using tlll = tuple<ll, ll, ll>;
constexpr ll INF = 1LL << 60;
template<class T> bool chmin(T& a, T b) {if (a > b) {a = b; return true;} return false;}
template<class T> bool chmax(T& a, T b) {if (a < b) {a = b; return true;} return false;}
ll safemod(ll A, ll M) {ll res = A % M; if (res < 0) res += M; return res;}
ll divfloor(ll A, ll B) {if (B < 0) A = -A, B = -B; return (A - safemod(A, B)) / B;}
ll divceil(ll A, ll B) {if (B < 0) A = -A, B = -B; return divfloor(A + B - 1, B);}
ll pow_ll(ll A, ll B) {if (A == 0 || A == 1) {return A;} if (A == -1) {return B & 1 ? -1 : 1;} ll res = 1; for (int i = 0; i < B; i++) {res *= A;} return res;}
ll mul_limited(ll A, ll B, ll M = INF) { return B == 0 ? 0 : A > M / B ? M : A * B; }
ll pow_limited(ll A, ll B, ll M = INF) { if (A == 0 || A == 1) {return A;} ll res = 1; for (int i = 0; i < B; i++) {if (res > M / A) return M; res *= A;} return res;}
template<class T> void unique(vector<T> &V) {V.erase(unique(V.begin(), V.end()), V.end());}
template<class T> void sortunique(vector<T> &V) {sort(V.begin(), V.end()); V.erase(unique(V.begin(), V.end()), V.end());}
#define FINALANS(A) do {cout << (A) << '\n'; exit(0);} while (false)
template<class T> void printvec(const vector<T> &V) {int _n = V.size(); for (int i = 0; i < _n; i++) cout << V[i] << (i == _n - 1 ? "" : " ");cout << '\n';}
template<class T> void printvect(const vector<T> &V) {for (auto v : V) cout << v << '\n';}
template<class T> void printvec2(const vector<vector<T>> &V) {for (auto &v : V) printvec(v);}
//*
#include <atcoder/all>
using namespace atcoder;
using mint = modint998244353;
//using mint = modint1000000007;
//using mint = modint;
//*/

struct BracketToTree
{
  bool ok;                      // 対応が取れているか
  vector<int> mypair;           // 文字の index → 対応している文字の index
  vector<int> itov;             // 文字の index → 頂点の index
  vector<pair<int, int>> vtoi;  // 頂点の index → 文字の index
  vector<int> par;              // 頂点の index → 親となる頂点の index (根は 0)
  
  BracketToTree() {}
  BracketToTree(const string &s, const char left = '(', const char right = ')')
  {
    const int n = s.size();
    mypair.resize(n, -1), itov.resize(n, -1), vtoi.resize(n / 2 + 1, make_pair(-1, -1)), par.resize(n / 2 + 1, -1);
    int v = 0;
    stack<int> sta;
    for (int i = 0; i < n; i++)
    {
      if (s[i] == left)
      {
        sta.push(i);
        itov[i] = ++v;
      }
      else if (s[i] == right)
      {
        if (sta.empty())
        {
          ok = false;
          return;
        }
        int j = sta.top();
        sta.pop();
        int u = itov[j];
        itov[i] = u;
        vtoi[u] = make_pair(j, i);
        mypair[j] = i, mypair[i] = j;
        int p = sta.empty() ? 0 : itov[sta.top()];
        par[u] = p;
      }
      else
        assert(false);
    }
    ok = sta.empty();
  }
};

template <typename Cost>
struct Edge
{
  int from, to;
  Cost cost;
  Edge(int s, int t, Cost c = 1) : from(s), to(t), cost(c) {}
  operator int() const { return to; }
};
template <typename Cost>
struct Graph : vector<vector<Edge<Cost>>>
{
  Graph(int n) : vector<vector<Edge<Cost>>>(n) {}
  void add_edge(int s, int t, Cost c = 1) { (*this)[s].emplace_back(s, t, c); }
  void add_edge2(int s, int t, Cost c = 1) { add_edge(s, t, c), add_edge(t, s, c); }
};

template<typename Cost>
struct LowestCommonAncestor : Graph<Cost>
{
  vector<vector<int>> par;
  vector<int> dep;
  vector<Cost> dists;

  LowestCommonAncestor(int n) : Graph<Cost>::Graph(n) {}

  void run(const int root = 0)
  {
    par.resize(log2((*this).size()) + 1);
    for (int i = 0; i < (int)par.size(); i++)
      par[i].resize((*this).size());
    dep.resize((*this).size()), dists.resize((*this).size());
    par[0][root] = -1, dep[root] = 0, dists[root] = 0;
    dfs(root, -1);
    doubling();
  }

  void dfs(int v, int pv)
  {
    //* bfs
    queue<pair<int, int>> que;
    que.emplace(make_pair(v, pv));
    while (!que.empty())
    {
      v = que.front().first, pv = que.front().second;
      que.pop();
      for (auto nv : (*this)[v])
      {
        if (nv == pv)
          continue;
        par[0][nv] = v;
        dep[nv] = dep[v] + 1;
        dists[nv] = dists[v] + nv.cost;
        que.emplace(make_pair(nv, v));
      }
    }
    //*/
    /* dfs
    for (auto nv : (*this)[v])
    {
      if (nv == pv)
        continue;
      par[0][nv] = v;
      dep[nv] = dep[v] + 1;
      dists[nv] = dists[v] + nv.cost;
      dfs(nv, v);
    }
    //*/
  }

  void doubling()
  {
    for (int i = 1; i < (int)par.size(); i++)
    {
      for (int v = 0; v < (int)(*this).size(); v++)
      {
        if (par[i - 1][v] == -1)
          par[i][v] = -1;
        else
          par[i][v] = par[i - 1][par[i - 1][v]];
      }
    }
  }

  int query_ancestor(int v, int k)
  {
    for (int i = (int)par.size() - 1; i >= 0; i--)
    {
      if (k & (1 << i))
        v = par[i][v];
      if (v == -1)
        return -1;
    }
    return v;
  }

  int query_lca(int u, int v)
  {
    if (dep[u] < dep[v])
      swap(u, v);
    
    u = query_ancestor(u, dep[u] - dep[v]);
    if (u == v)
      return u;
    for (int i = (int)par.size() - 1; i >= 0; i--)
    {
      if (par[i][u] != par[i][v])
        u = par[i][u], v = par[i][v];
    }
    return par[0][u];
  }

  int query_dist1(int u, int v)
  {
    return dep[u] + dep[v] - 2 * dep[query_lca(u, v)];
  }
  Cost query_dist(int u, int v)
  {
    return dists[u] + dists[v] - 2 * dists[query_lca(u, v)];
  }

  int query_jump(int s, int t, int k)
  {
    int u = query_lca(s, t);
    if (k <= dep[s] - dep[u])
      return query_ancestor(s, k);
    int k2 = dep[s] + dep[t] - 2 * dep[u] - k;
    return k2 < 0 ? -1 : query_ancestor(t, k2);
  }
};

int main()
{
  ll N, Q;
  string S;
  cin >> N >> Q >> S;
  BracketToTree bt(S);
  LowestCommonAncestor<ll> G(N / 2 + 1);
  for (ll i = 1; i <= N / 2; i++)
  {
    G.add_edge2(i, bt.par.at(i));
  }
  G.run();
  while (Q--)
  {
    ll x, y;
    cin >> x >> y;
    x--, y--;
    ll u = bt.itov.at(x), v = bt.itov.at(y);
    ll w = G.query_lca(u, v);
    if (w == 0)
      cout << -1 << endl;
    else
    { 
      auto [i, j] = bt.vtoi.at(w);
      cout << i + 1 << " " << j + 1 << endl;
    }
  }
}
0