题意:给出一个由"(",")","?"三种字符构成的序列,让我们把其中的问号替换成左右括号,使得整个序列变成一个完整地括号序列,也就是括号匹配正确,而且要求不能提前结束的括号序列,比如(())()...这种的就是提前结束的括号序列,一定要让整个序列的最后一个右括号字符正好匹配上字符串的第一个左括号字符。输出任意一种方案。
分析:首先想到奇数长度的时候必定错误,第一个括号是),或最后一个括号是(都会出现错误。因为匹配必定错误
那么如果括号在中间的任何一个地方发现了与第一个左括号匹配也错误,那么相当于尽可能的先写左括号,能写左括号的地方写左括号,直到左括号的数量足够多了,等于n/2的时候再贪心的写右括号。如果能在解题的时候看透这一点,程序就很好写了。
这样贪心正确的原因是:错误的情况必定是左括号太少以至于匹配不了这么多右括号,所以正确的case必定是前面留有足够的空间放置左括号去匹配后面的右括号。所以只要是问号,且当前确定的左括号数量不到n/2,就直接放左括号就行,直到已经确定的左括号数量到n/2再不断放右括号。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn = 3e5+10;
char c[maxn];
void fail(){printf(":(");exit(0);}
int main(){int n;scanf("%d%s",&n,c);if((n%2==1)||c[0]==')'||c[n-1]=='(')fail();int bal=0,ll=0;for(int i=0;i<n;i++)if(c[i]=='(')ll++;for(int i=0;i<n;i++){if(c[i]=='(')bal++;if(c[i]==')')bal--;if(c[i]=='?'){if(ll<n/2)c[i]='(',bal++,ll++;else c[i]=')',bal--;}if(i!=n-1&&bal==0)fail();}if(bal!=0)fail();else printf("%s\n",c);return 0;
}