题解:AT_arc175_b [ARC175B] Parenthesis Arrangemen

前言

警示后人:

字符串最大长度为 \(65535\) ,会 \(RE\) !!!

\(10^7\) 会爆栈!!!

题意

给出一个括号序列 \(s\) ,有两种操作方式,交换两个字符需要花费 \(A\) ,直接修改一个字符需要花费 \(B\) ,求使这个序列合法需要的最小花费。

分析

我们可以先将 \(s\) 中能匹配的括号序列消除掉(即括号匹配)。

最后的字符串会由 \(l\))\(r\)( 组成。

这个时候我们可以发现交换两个字符和在原串交换是等价的。

那么我们可以 贪心

我们可以考虑:

  • 先把可以交换的交换,然后替换剩下不可交换的。

  • 全部替换。

最后取最小值即可。

#include<bits/stdc++.h>
#define int long long
#define fd(i,a,b) for(int i=a;i<=b;i=-~i)
using namespace std;
int a,b,n,l,r,tot=0;
char s[10001000],q[10001000];
//自带的stack会RE(考后才发现)
void push(char ch){q[++tot]=ch;}
char top(){return q[tot];}
void pop(){if(tot>0) --tot;}
bool empty(){return tot>0?0:1;}
//以上是手写栈(dalao勿喷)
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>n>>a>>b;
	cin>>s[1];
	push(s[1]);
	fd(i,2,n*2)
	{
		cin>>s[i];
		if(top()=='('&&s[i]==')') pop();
		else push(s[i]);
	}
	if(empty())
	{
		cout<<0;
		return 0;
	}
	while(!empty())
	{
		if(top()=='(') r++;
		else l++;
		pop();
	}
	if(l>r) swap(l,r);
	if(l&1) cout<<min((l+1)/2*a+(r-l)/2*b,(l+r)/2*b+b);
	else cout<<min((l+1)/2*a+(r-l)/2*b,(l+r)/2*b);
	return 0;
}
posted @ 2024-03-31 17:17  whrwlx  阅读(5)  评论(0编辑  收藏  举报