結果
| 問題 | No.2591 安上がりな括弧列 | 
| コンテスト | |
| ユーザー |  | 
| 提出日時 | 2023-12-19 03:46:00 | 
| 言語 | C++17(clang) (17.0.6 + boost 1.87.0) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 6 ms / 2,000 ms | 
| コード長 | 5,738 bytes | 
| コンパイル時間 | 1,217 ms | 
| コンパイル使用メモリ | 146,944 KB | 
| 実行使用メモリ | 6,944 KB | 
| 最終ジャッジ日時 | 2024-09-27 08:36:32 | 
| 合計ジャッジ時間 | 2,029 ms | 
| ジャッジサーバーID (参考情報) | judge2 / judge1 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| other | AC * 23 | 
ソースコード
/*
g++ -O2 --std=c++17 -D LOCAL A.cpp
*/
#include <iostream>
#include <iomanip>
#include <math.h>
#include <algorithm>
#include <functional> 
#include <string>
#include <vector>
#include <cstring>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <utility>
#include <limits.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#ifdef LOCAL
#define dlog(x) { cerr << '[' << __LINE__ << "] " << x << endl; }
#define dvar(v) { cerr << '[' << __LINE__ << "] " << #v << " = " << v << endl; }
#define dvec(c) { cerr << '[' << __LINE__ << "] " << #c << " = "; for (int i = 0; i < c.size(); ++i) if (i == 0) cerr << '['<<i<<']'<<c[i]; else cerr << " ["<<i<<']'<<c[i]; cerr << endl; } 
#define dmap(m) { cerr << '[' << __LINE__ << "] " << #m << " = "; for (auto it: m) cerr << it.first << "=>" << it.second << ' '; cerr << endl; }
#define dset(s) { cerr << '[' << __LINE__ << "] " << #s << " = "; for (auto item: s) cerr << item << ' '; cerr << endl; }
#else
#define dlog(x)
#define dvar(v)
#define dvec(c)
#define dmap(m)
#define dset(s)
#endif
#define rep(i,n) for (int i = 0; i < int(n); ++i)
#define repr(i,from,to) for (int i = int(from); i <= int(to); ++i)
#define rrep(i,n) for (int i = (n)-1; 0 <= i; --i)
#define rrepr(i,from,to) for (int i = int(from); int(to) <= i; --i)
#define endl '\n'
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define dump(c) { for (auto it = c.begin(); it != c.end(); ++it) if (it == c.begin()) cout << *it; else cout << ' ' << *it; cout << endl; } 
typedef pair<int, int> P;
typedef pair<LL, LL> LP;
#ifndef F
#define F first
#define S second
#endif 
#ifndef umap
#define umap unordered_map
#endif
#ifndef uset
#define uset unordered_set
#endif
template<typename T1, typename T2>
ostream& operator<<(ostream& os, const pair<T1, T2>& p) {
  return os << p.F << ':' << p.S;
}
/*
  == AC Library Cheat sheet
  documentation: file:///Users/nobu/Downloads/ac-library/document_ja/index.html
  mint
    mint m.pow(int p)  //! return m^p
    mint m.inv() //! returns i that gives (m * i).val() == 1 
    int m.val() 
  fenwick_tree (BIT)
    fenwick_tree<T> fw(int n) //! init a[0] .. a[n-1] with all 0
    void fw.add(int idx, T x); //! a[idx] += x
    T fw.sum(int l, int r); //! return a[l] + .. + a[r-1]
  dsu (UnionFind)
    dsu d(int n)  //! prepare dsu with n nodes
    void d.merge(int x, int y)  //! connect node x and y
    bool d.same(int x, int y)  //! return true if node x and y are connected
    int d.leader(int x)  //! return the leader node of the connected group
    int d.size(int x) //! return the size of the group that node x belongs to
    vector<vector<int>> d.groups() //! return a vector of vectors that contain the nodes in each group
  scc_graph
    scc_graph g(int n)  //! create a directed graph with n nodes
    g.add_edge(int from, int to)  //! create a directed edge from node from to node to
    vector<vector<int>> g.scc()  //! return the vector of strongly connected components that are topologically sorted
  segtree
    segtree<S, op, e>
      S: type of the monoid 
      op: function to return the product of two elements
      e: function to return the identity element such that op(x, e) == x fo any x 
  lazy_segtree
    lazy_segtree<S, op, e, F, mapping, composition, id>
      F: type of parameters to define the operation applied to the target elements
      mapping: function to return the element after applying the operation to the target element
      composition: function to combine the two sets of operation parameters to one
      id: function to return the operation parameter i such that mapping(i, x) = x for any x
      using S = int;
      S op(S a, S b) { return min(a, b); }
      S e() { return INF; }
      using F = int;
      S mapping(F f, S x) { return min(f, x); }
      F composition(F f, F g) { return min(f, g); }
      F id() { return INF; }
*/
// int dx[] = { 0, -1, 1, 0 };
// int dy[] = { -1, 0, 0, 1 };
// int dx[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
// int dy[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
const int INF = 2e9+1e4;
const LL INFL = 4e18+1e9;
const int MOD = 998244353;
// #define USE_ACL
#ifdef USE_ACL
#include <atcoder/all>
using namespace atcoder;
using mint = static_modint<MOD>;
struct combination {
  vector<mint> fact, ifact;
  combination(int n):fact(n+1),ifact(n+1) {
    assert(n < MOD);
    fact[0] = 1;
    for (int i = 1; i <= n; ++i) fact[i] = fact[i-1]*i;
    ifact[n] = fact[n].inv();
    for (int i = n; i >= 1; --i) ifact[i-1] = ifact[i]*i;
  }
  mint operator()(int n, int k) {
    if (k < 0 || k > n) return 0;
    if ((int)fact.size() <= n) return smallk(n, k);
    return fact[n]*ifact[k]*ifact[n-k];
  }
  mint smallk(int n, int k) {
    if (n-k < k) k = n-k;
    assert(k < (int)fact.size());
    mint ret = 1;
    for (int i = n-k+1; i <= n; ++i) ret *= i;
    return ret*ifact[k];
  }
};
ostream& operator<<(ostream& os, const mint& i) {
  return os << i.val();
}
#endif
int main()
{
  cin.tie(0);
  ios::sync_with_stdio(0);
  cout << setprecision(20);
  int n;
  string s;
  cin >> n >> s;
  vector<int> a(2*n);
  rep(i, 2*n) cin >> a[i];
  vector<LL> dp(n+1, INFL);
  dp[0] = 0;
  rep(i, 2*n) {
    vector<LL> next(n+1, INFL);
    if (s[i] == '(') {
      rep(j, n) chmin(next[j+1], dp[j]);
      repr(j, 1, n) chmin(next[j-1], dp[j]+a[i]);
    } else if (s[i] == ')') {
      rep(j, n) chmin(next[j+1], dp[j]+a[i]);
      repr(j, 1, n) chmin(next[j-1], dp[j]);
    }
    dp.swap(next);
  }
  cout << dp[0] << endl;
  cout << flush;
  return 0;
}
            
            
            
        