前言
警示後人:
字串最大長度為 \(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;
}