結果

問題 No.3539 Parentheses Square
コンテスト
ユーザー 👑 Nachia
提出日時 2026-05-08 22:24:05
言語 C++17
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++17 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 63 ms / 2,000 ms
コード長 5,746 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,000 ms
コンパイル使用メモリ 128,464 KB
実行使用メモリ 24,832 KB
最終ジャッジ日時 2026-05-08 22:24:11
合計ジャッジ時間 4,516 ms
ジャッジサーバーID
(参考情報)
judge3_0 / judge2_1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 3
other AC * 41
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#ifdef NACHIA
#define _GLIBCXX_DEBUG
#else
// disable assert
#define NDEBUG
#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i,n) for(ll i=0; i<ll(n); i++)
template <class T> using V = vector<T>;
template <class A, class B> void chmax(A& l, const B& r){ if(l < r) l = r; }
template <class A, class B> void chmin(A& l, const B& r){ if(r < l) l = r; }

V<string> concrete(string T, ll mx){
  ll N = T.size() / 2;
  V<V<int>> dp(N+2, V<int>(N+2));
  dp[0][0] = 1;
  REP(i,N+1) REP(j,N+1) if(i+j < N*2) if(dp[i][j]){
    if(i > j){ dp[i][j] = 0; continue; }
    if(T[i+j] != ')') dp[i][j+1] = 1;
    if(T[i+j] != '(') dp[i+1][j] = 1;
  }
  V<string> ans;
  string buf = T;
  auto dfs = [&](auto& dfs, ll i, ll j) -> void {
    if(ans.size() == mx) return;
    if(dp[i][j] == 0) return;
    if(i + j == 0){ ans.push_back(buf); return; }
    if(j && T[i+j-1] != ')'){ buf[i+j-1] = '('; dfs(dfs, i, j-1); }
    if(i && T[i+j-1] != '('){ buf[i+j-1] = ')'; dfs(dfs, i-1, j); }
  };
  dfs(dfs, N, N);
  return ans;
}

#include <utility>

namespace nachia{

template<class Elem>
class CsrArray{
public:
    struct ListRange{
        using iterator = typename std::vector<Elem>::iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        Elem& operator[](int i) const { return begi[i]; }
    };
    struct ConstListRange{
        using iterator = typename std::vector<Elem>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const Elem& operator[](int i) const { return begi[i]; }
    };
private:
    int m_n;
    std::vector<Elem> m_list;
    std::vector<int> m_pos;
public:
    CsrArray() : m_n(0), m_list(), m_pos() {}
    static CsrArray Construct(int n, std::vector<std::pair<int, Elem>> items){
        CsrArray res;
        res.m_n = n;
        std::vector<int> buf(n+1, 0);
        for(auto& [u,v] : items){ ++buf[u]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.m_list.resize(buf[n]);
        for(int i=(int)items.size()-1; i>=0; i--){
            res.m_list[--buf[items[i].first]] = std::move(items[i].second);
        }
        res.m_pos = std::move(buf);
        return res;
    }
    static CsrArray FromRaw(std::vector<Elem> list, std::vector<int> pos){
        CsrArray res;
        res.m_n = pos.size() - 1;
        res.m_list = std::move(list);
        res.m_pos = std::move(pos);
        return res;
    }
    ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    int size() const { return m_n; }
    int fullSize() const { return (int)m_list.size(); }
};

} // namespace nachia

namespace nachia{

std::vector<int> BipertiteMatching(int N1, int N2, const std::vector<std::pair<int, int>>& edges){
    std::vector<int> R(N2, -1);
    std::vector<int> L(N1, -1);
    auto E = CsrArray<int>::Construct(N1, edges);
    while(true){
        std::vector<int> bfs, dist(N1, -1), P(N1, -1);
        for(int i=0; i<N1; i++) if(L[i] == -1){ bfs.push_back(i); dist[i] = 0; }
        int maxD = N1 + 1;
        for(size_t i=0; i<bfs.size(); i++){
            int p = bfs[i];
            if(dist[p] >= maxD) break;
            for(int e : E[p]) if(L[p] != e){
                if(R[e] >= 0){
                    if(dist[R[e]] < 0){
                        dist[R[e]] = dist[p] + 1;
                        P[R[e]] = p;
                        bfs.push_back(R[e]);
                    }
                }
                else maxD = dist[p];
            }
        }
        if(maxD > N1) break;
        std::vector<int> I(N1, 0);
        for(int s=0; s<N1; s++) if(L[s] == -1){
            int p = s, p2;
            while(p >= 0){
                if(I[p] == E[p].size()){ p = P[p]; continue; }
                int q = E[p][I[p]++];
                int r = R[q];
                if(r == -1){ p2 = q; break; }
                if(dist[r] != dist[p] + 1) continue;
                P[r] = p;
                p = r;
            }
            if(p < 0) continue;
            while(p >= 0){
                R[p2] = p;
                std::swap(L[p], p2);
                p = P[p];
            }
        }
    }
    std::vector<int> ans;
    for(int i=0; i<(int)edges.size(); i++){
        auto& e = edges[i];
        if(L[e.first] == e.second){ L[e.first] = -1; ans.push_back(i); }
    }
    return ans;
}

} // namespace nachia

void testcase(){
  ll N; cin >> N;
  V<string> T(N); REP(i,N) cin >> T[i];
  if(N%2 == 1){ cout << "-1\n"; return; }
  V<string> mapping;
  V<V<string>> conc(N);
  REP(i,N){
    conc[i] = concrete(T[i], N);
    for(auto& a : conc[i]) mapping.push_back(a);
  }
  REP(i,N) if(conc[i].empty()){ cout << "-1\n"; return; }
  sort(mapping.begin(), mapping.end());
  mapping.erase(unique(mapping.begin(), mapping.end()), mapping.end());
  V<pair<int,int>> sha;
  REP(i,N) for(auto& a : conc[i]) sha.push_back({i,lower_bound(mapping.begin(), mapping.end(), a) - mapping.begin()});
  auto mch = nachia::BipertiteMatching(N, mapping.size(), sha);
  V<ll> ch(N, -1);
  for(auto a : mch) if(a >= 0) ch[sha[a].first] = sha[a].second;
  REP(i,N) if(ch[i] < 0){ cout << "-1\n"; return; }
  REP(i,N) cout << mapping[ch[i]] << "\n";
}

int main(){
  cin.tie(0)->sync_with_stdio(0);
  testcase();
  return 0;
}
0