清北学堂
清北学堂 11.23
A
给定一个括号串,求最少进行多少次“交换两个相邻的字符"能使该括号串合法
空串是合法括号串
如果A是合法括号串,则(A)是合法括号串
如果A,B是合法括号串,则A,B是合法括号串
肯定先要满足前面的不匹配的右括号,但这样会对后面移动的距离产生一定的影响。
比如))((
- )()(
- ())(
- ()()
其次如果前面已经匹配的括号对可以直接抵消,不会对后面产生影响
这样大概率就可以线性计算了。
考虑如何计算交换次数:
官方说把他看成一个折线图,规定左括号为斜向上,右括号为斜向下。如果纵坐标小于0,那么
画出括号序列的折线图。
答案即为 ∑⌈max(−pi,0)/2⌉ 。其中 pi 表示横坐标为 i 时的纵坐标。
为什么?
我们考虑一次交换左右两个括号的实质。
以左边是右括号为例,那么这个过程等价于把 pi+=2 。
那么答案显然是上述式子。
时间复杂度 O(n),空间复杂度 O(1) 。
但我很奇怪为什么要有(-pi,0)/2
这样不是好理解多了吗
#include<bits/stdc++.h>
using namespace std;
string s;
#define rt register int
int n;
long long res,ans;
inline string sread(){
string ans;
char ch=getchar();
while(ch==' '||ch=='\n'||ch=='\t') ch=getchar();
while(ch!=' '&&ch!='\n'&&ch!='\t') ans+=ch,ch=getchar();
return ans;
}
int main()
{
s=sread();
n=s.length();
for(rt i=0;i<n;++i)
{
if(s[i]=='(')
{
if(res<0)ans+=abs(res);
res+=1;
}else res--;
}
cout<<ans<<endl;
}