Skip to content
本博客自 2023 年 4 月 4 日起转为归档状态,可能不再发表新的博文。点此了解博主的竞赛生涯
This blog has been archived by the owner since April 4, 2023. It may no longer have new updates.

AtCoder - AGC048B Bracket Score

题解542 字
检测到 KaTeX 加载失败,可能会导致文中的数学公式无法正常渲染。

#题面

#题目描述

给定一个偶数 NN 和长度为 NN 的整数序列 AABB。在这里,我们为一个长度为 NN 的括号序列 ss 定义一个分数:

  • ss 的总分是其中每个字符的分数的总和;
  • ii 个字符若是 (),则分数为 AiA_i,否则分数为 BiB_i

请你构造出一个括号序列,使得这个括号序列的分数最大。

#输入格式

第一行一个整数 NN

第二行 NN 个整数表示 AA 序列。

第三行 NN 个整数表示 BB 序列。

#输出格式

一行一个整数,表示最大分数。

#数据范围与约定

对于 100%100\% 的数据,2N1052 \leq N \leq 10^51Ai,Bi1091 \leq A_i, B_i \leq 10^9

#思路

由括号序列的性质得出,一对匹配的括号的间距一定是偶数,即它们两个的位置的奇偶性不同。

还能发现,一旦每个位置上的括号类型(圆/方括号)确定且一对匹配的括号的间距是偶数,一定能找到一种确定括号朝向的方法使得序列合法。

可以使用贪心解决本题。

先钦定全部选择圆括号,然后对于每个位置,计算将它改为方括号对答案的影响。那么可以将改动奇数位置和改动偶数位置对答案的影响分别放入两个堆中,每次分别取出两个堆的堆顶,将对应的位置改为方括号,直到再取堆顶答案不会更优为止。

#代码

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <queue>

using std::cin;
using std::cout;
const char endl = '\n';

const int N = 1e5 + 5;

int n, a[N], b[N];
long long ans;
std::priority_queue<int> q1, q2;

int main() {
std::ios::sync_with_stdio(false);

cin >> n;

for (int i = 1; i <= n; i++) {
cin >> a[i];

ans += a[i];
}

for (int i = 1; i <= n; i++) {
cin >> b[i];

(!(i & 1) ? q1 : q2).push(b[i] - a[i]);
}

while (!q1.empty()) {
int t = q1.top() + q2.top();
q1.pop(), q2.pop();

if (t <= 0) break;
ans += t;
}

cout << ans << endl;

return 0;
}