• CF1153C. Serval and Parenthesis Sequence


    题意

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

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

    无法构造输出:(

    题解

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

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

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

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

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

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

    #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);
    }
    
  • 相关阅读:
    艾氏筛法资料
    CF Soldier and Cards (模拟)
    CF Soldier and Badges (贪心)
    POJ 1308 Is It A Tree? (并查集)
    HDU 1272 小希的迷宫 (并查集)
    HDU 1213 How Many Tables (并查集)
    POJ 1611 The Suspects (并查集)
    POJ 2236 Wireless Network (并查集)
    Iptables-linux服务器做路由转发
    asdf
  • 原文地址:https://www.cnblogs.com/henry-1202/p/10859410.html
Copyright © 2020-2023  润新知