Parenthesis Arrangement
传送门
Problem Statement
You are given a string
S
S
S of length
2
N
2N
2N consisting of the characters (
and )
. Let
S
i
S_i
Si denote the
i
i
i-th character from the left of
S
S
S.
You can perform the following two types of operations zero or more times in any order:
-
Choose a pair of integers ( i , j ) (i,j) (i,j) such that 1 ≤ i < j ≤ 2 N 1\leq i < j \leq 2N 1≤i<j≤2N. Swap S i S_i Si and S j S_j Sj. The cost of this operation is A A A.
-
Choose an integer i i i such that 1 ≤ i ≤ 2 N 1\leq i \leq 2N 1≤i≤2N. Replace S i S_i Si with
(
or)
. The cost of this operation is B B B.
Your goal is to make S S S a correct parenthesis sequence. Find the minimum total cost required to achieve this goal. It can be proved that the goal can always be achieved with a finite number of operations.
What is a correct parenthesis sequence? A correct parenthesis sequence is a string that satisfies any of the following conditions:
- It is an empty string.
- It is formed by concatenating
(
, A A A,)
in this order where A A A is a correct parenthesis sequence. - It is formed by concatenating A A A and B B B in this order where A A A and B B B are correct parenthesis sequences.
Constraints
- All input values are integers.
- 1 ≤ N ≤ 5 × 1 0 5 1 \leq N \leq 5\times 10^5 1≤N≤5×105
- 1 ≤ A , B ≤ 1 0 9 1\leq A,B\leq 10^9 1≤A,B≤109
-
S
S
S is a string of length
2
N
2N
2N consisting of the characters
(
and)
.
Input
The Input is given from Standard Input in the following format:
N N N A A A B B B
S S S
Output
Print the answer in a single line.
Sample Input 1
3 3 2
)))(()
Sample Output 1
5
Here is one way to operate:
- Swap
S
3
S_3
S3 and
S
4
S_4
S4.
S
S
S becomes
))()()
. The cost is 3 3 3. - Replace
S
1
S_1
S1 with
(
. S S S becomes()()()
, which is a correct parentheses sequence. The cost is 2 2 2.
In this case, we have made S S S a correct bracket sequence for a total cost of 5 5 5. There is no way to make S S S a correct bracket sequence for less than 5 5 5.
Sample Input 2
1 175 1000000000
()
Sample Output 2
0
The given S S S is already a correct bracket sequence, so no operation is needed.
Sample Input 3
7 2622 26092458
))()((((()()((
Sample Output 3
52187538
题目翻译
题目描述
给你一个长度为
2
N
2N
2N 的字符串
S
S
S ,由字符 (
和 )
组成。让
S
i
S_i
Si 表示
S
S
S 左边的第
i
i
i 个字符。
您可以按任意顺序执行以下两种类型的操作零次或多次:
-
选择一对整数 ( i , j ) (i,j) (i,j) 使得 1 ≤ i < j ≤ 2 N 1\leq i < j \leq 2N 1≤i<j≤2N .交换 S i S_i Si 和 S j S_j Sj 。这一操作的代价是 A A A 。
-
选择一个整数 i i i ,使得 1 ≤ i ≤ 2 N 1\leq i \leq 2N 1≤i≤2N .将 S i S_i Si 替换为
(
或)
。这个操作的代价是 B B B 。
您的目标是使 S S S 成为一个正确的括号序列。求实现这一目标所需的最小总成本。可以证明,用有限次的运算总能达到目标。
什么是正确的括号序列?正确的括号序列是满足以下任意条件的字符串:
- 它是空字符串。
- 它是由
(
, A A A ,)
按此顺序连接而成,其中 A A A 是一个正确的括号序列。 - 由 A A A 和 B B B 依次连接而成,其中 A A A 和 B B B 是正确的括号序列。
数据范围
- 所有输入值均为整数。
- 1 ≤ N ≤ 5 × 1 0 5 1 \leq N \leq 5\times 10^5 1≤N≤5×105
- 1 ≤ A , B ≤ 1 0 9 1\leq A,B\leq 10^9 1≤A,B≤109
-
S
S
S 是长度为
2
N
2N
2N 的字符串,由字符
(
和)
组成。
输入
输入内容由标准输入法提供,格式如下:
N N N A A A B B B
S S S
输出
单行打印答案。
提示
对于样例 #1 输出的解释
下面是一种操作方法:
- 交换
S
3
S_3
S3 和
S
4
S_4
S4 。
S
S
S 变成了
))()()()
。代价是 3 3 3 。 - 将
S
1
S_1
S1 替换为
(
。 S S S 变成()()()
,这是一个正确的括号序列。代价是 2 2 2 。
在这种情况下,我们将 S S S 变为一个正确的括号序列,总费用为 5 5 5 。我们无法以低于 5 5 5 的代价使 S S S 成为一个正确的括号序列。
对于样例 #2 输出的解释
给出的 S S S 已经是一个正确的括号序列,因此无需进行任何操作。
注明
以上来自
A
t
C
o
d
e
r
,翻译来源:
D
e
e
p
L
。
以上来自 AtCoder,翻译来源:DeepL。
以上来自AtCoder,翻译来源:DeepL。
翻译插件:AtCoder Better。
解题思路
先用一个字符串顺序存下不符合题目要求的括号,然后分别记录下其中左括号和有括号的数量。如果交换括号对的代价小于改变一对括号的代价,即 A < B × 2 A < B \times 2 A<B×2,那么就交换否则替换。若交换后仍然有剩余的括号,则只能进行替换。若剩下的左括号数量不为 2 2 2 的倍数,则须再单独取出一个括号替换。即以下输入情况:
)()()(
AC Code
#include <bits/stdc++.h>
using namespace std;
long long N, A, B;
string S;
long long Answer;
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0), cin >> N >> A >> B >> S;
string s;
for (int i = 0, count_left = 0; i < S.size(); i++) {
if (S[i] == '(') count_left++, s.push_back('(');
if (S[i] == ')') if (count_left >= 1) count_left--, s.pop_back();
else s.push_back(')');
}
long long left_count = 0, right_count = 0;
for (int i = 0; i < s.size(); i++) if (s[i] == '(') left_count++;
else if (s[i] == ')') right_count++;
if (left_count && right_count && A < B * 2) {
int _min = min(left_count, right_count);
Answer += _min / 2 * A;
if (_min % 2 == 1) Answer += A;
left_count -= _min, right_count -= _min;
}
if (left_count) Answer += left_count / 2 * B;
if (right_count) Answer += right_count / 2 * B;
if (left_count & 1) Answer += 2 * B;
cout << Answer << endl;
return 0;
}