【AGC048B】Bracket Score
题目
题目链接:https://atcoder.jp/contests/agc048/tasks/agc048_b
一个合法括号序列是包括小括号和中括号的。
给定长度为 \(n\) 的数组 \(a\) 和 \(b\),一个长度为 \(n\) 的括号序列的权值为每个字符的权值之和,对于第 \(i\) 个字符,当其为 (
或 )
时,权值为 \(a_i\);当其为 [
或 ]
时,权值为 \(b_i\)。问一个长度为 \(n\) 括号序列的权值最大为多少。
\(n\leq 10^5,a,b\leq 10^9\)。\(n\) 是偶数。
思路
容易发现一对括号所在位置一定是一奇一偶,所以最终合法括号序列的小括号在奇数位置上的数量和在偶数位置上的数量相同。中括号同理。
可以证明如果小括号和中括号都满足在奇数位置上的数量与在偶数位置上的数量相同,那么必然存在一组这样的合法括号序列。
具体的,假设小括号数量大于中括号数量,那么必然存在一对相邻的小括号,删去这一对小括号后转化为子问题。
如果小括号数量等于中括号数量,为了防止出现连续两个位置填入同一括号,一定是 ([([
这样排列,但是这样最中间两个括号一定是相同的。删去之后也可以形成一个子问题。
简单归纳一下即可。
所以我们只需要在满足两种括号在奇偶位置上数量分别相同即可。所以我们把奇偶位置分开,按照 \(a-b\) 排序,然后贪心选取即可。
时间复杂度 \(O(n\log n)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
int n;
ll ans;
struct node
{
int a,b;
}a[2][N];
bool cmp(node x,node y)
{
return x.a-x.b>y.a-y.b;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i&1][(i+1)/2].a);
for (int i=1;i<=n;i++)
scanf("%d",&a[i&1][(i+1)/2].b);
sort(a[0]+1,a[0]+1+n/2,cmp);
sort(a[1]+1,a[1]+1+n/2,cmp);
for (int i=1;i<=n;i++)
ans+=max(a[0][i].a+a[1][i].a,a[0][i].b+a[1][i].b);
printf("%lld\n",ans);
return 0;
}