给出一段仅由左右括号组成的字符串,和若干个区间(L,R) (各个区间不重叠),问要使每个区间内的序列都合法,最少需要进行多少次交换(每次交换可以互换任意两个位置上的字符)。
思路
<1>对于每一个的区间一定要满足的是: ( 个数始终大于)于是每次cnt[1]>cnt[0]时就使cnt[1]–,cnt[0]++,res++ 表示把)变成(的个数 res为A;
<2>最终造成 ( 多一些于是需要把(cnt[1]-cnt[0])/2个 ( 换成 ) 为B;
<3>如果A比B大就需要额外的)反之需要(
const int M=10005;
class ParenthesesDiv2Hard {
public:
bool G[M],use[M];int need[2],sum[2];
int minSwaps(string s, vector <int> L, vector <int> R) {
int n=s.size(),m=L.size(),ans=0;
for(int i=0;i<n;i++)G[i]=(s[i]==')');
for(int i=0;i<m;i++)
for(int j=L[i];j<=R[i];j++)use[j]=1;
for(int i=0;i<n;i++)if(!use[i])sum[G[i]]++;
for(int i=0;i<m;i++){
if((R[i]-L[i]+1)%2)return -1;
int sum=0,res=0;
//res:how many ')' should be change into '('
//sum:the sum of rest '('
for(int j=L[i];j<=R[i];j++){
if(!G[j])sum++;
else sum--;
if(sum<0)sum+=2,res++;
}
sum/=2;
//sum:'(' was rest and should be exchanged sum/2 times
//->sum/2:how many '(' should be change into ')'
ans+=min(sum,res);
if(res>sum)need[0]+=res-sum;
else need[1]+=sum-res;
}
int chang_inside=min(need[0],need[1]);
//min(need[0],need[1]):how many '(',')'can be fixed inside
if(need[0]-chang_inside>sum[0]||need[1]-chang_inside>sum[1])return -1;
ans+=max(need[0],need[1]);
//ans+=min(need[0],need[1])+max(need[0],need[1])-min(need[0],need[1]);
// which be exchanged inside || the rest '('or ')' also needs one time to fix;
return ans;
}
};