题意

给一个包含'(',')','?'的串,需要在'?'处填'('或')',使其满足

  • 每个严格前缀(严格前缀 指不是整个串的所有前缀)不是可匹配的括号序列
  • 整个串是可匹配的括号序列

无法构造输出:(

题解

其实就是构造一个首尾对应的括号序列。

那么把第一个和最后一个排除了,把中间的那些构造成一个合法的括号序列就行了。

至于怎么构造,使用贪心:

  • 首先先将能匹配的'('和')'给匹配了,并且尽量相近的匹配。
  • 然后用'?'位来补'('和')'剩下的。
  • 最后剩余的'?'位自己匹配自己。

最后判定一下这样构造出来的括号序列合不合法(如果不合法就说明构造不出来)即可。

好像写复杂了...看了一下别人的构造方法都很简短...

#include <bits/stdc++.h>
using namespace std;

#define ll long long
const int N = 300010;

int n, top;
char s[N];
bool vis[N];
int id[N];

int main() {
    scanf("%d", &n);
    scanf("%s", s + 1);
    if(s[1] == ')' || s[n] == '(') return puts(":("), 0;
    s[1] = '('; s[n] = ')';

    int cur = 1, tot = 0;
    for(int i = 2; i < n; ++i) if(s[i] == ')') id[++tot] = i;
    for(int i = 2; i < n; ++i) {
        if(s[i] == '(') {
            if(cur <= tot) {
                vis[id[cur]] = 1;
                vis[i] = 1;
                ++cur;
            }
        } 
        if(id[cur] == i) ++cur;
    }
    
    cur = n - 1;
    for(int i = 2; i < n; ++i) {
        if(s[i] == '(' && !vis[i]) {
            while(cur > 1 && ( s[cur] != '?' || (s[cur] == '?' && vis[cur]) ) ) 
                --cur;
            if(s[cur] == '?' && !vis[cur]) 
                vis[cur] = 1, s[cur] = ')', vis[i] = 1;
        } 
    }
    cur = 2;
    for(int i = n - 1; i > 1; --i) {
        if(s[i] == ')' && !vis[i]) {
            while(cur < n && ( s[cur] != '?' || (s[cur] == '?' && vis[cur] ) ) ) ++cur;
            if(s[cur] == '?' && !vis[cur]) vis[cur] = 1, s[cur] = '(', vis[i] = 1;
        }
    }
    
    bool flag = 0;
    top = 0;
    for(int i = 2; i < n; ++i) {
        if(s[i] == '?' && !vis[i]) {
            s[i] = flag ? ')' : '(';
            flag ^= 1;
        }
    }
    
    for(int i = 1; i <= n; ++i) {
        if(s[i] == '(') ++top;
        else --top;
        if(top <= 0 && i != n) return puts(":("), 0;
    }
    if(top != 0) return puts(":("), 0;
    puts(s + 1);
}