題解:AT_arc175_b [ARC175B] Parenthesis Arrangemen

whrwlx發表於2024-03-31

前言

警示後人:

字串最大長度為 \(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;
}