HDU 4915 多校5 Parenthese sequence

比赛的时候想了一个自认为对的方法,WA到死,然后还一直敲下去,一直到晚上才想到反例

找是否存在解比较好找,这种左右括号序列,把(当成1,把)当成-1,然后从前往后扫,+1或者-1 遇到?就当初(,然后如果扫到最后 中间没有出现负数说明左括号没问题

然后同样的方法从后往前扫,判断右括号那里是不是有问题即可。都没问题就有解,否则无解

当然应该要先判断下序列长度是不是偶数,奇数肯定是无解

至于为什么要像之前的处理即可判断有无解,首先只有正好走完的时候 和值为0才是真正合法(因为这个时候左右括号都对应了嘛)

他是偶数个+1或者-1,扫下来的和肯定也是偶数,只要扫到最后不出现负数,(出现负数说明中间有括号找不到匹配的括号)我们只要把中间的某些括号反向,最终一定可以使序列和值为0。所以正反两遍下来即可

最难的就是判断many和unique了,想了很多方法,依然做不好这一题(嘿嘿,盗用了后会无期的台词),还是最普遍的一种最好,即,判断是否有>=2个括号,正向和方向都可以

判断是否可行的方法就是上面的那个,但是我不可能暴力枚举每个括号,然后执行上面的操作,来判断他是否可行吧。。会超时的

所以要预处理一下,弄个prefix0代表i前面是否有前缀和<=1的,suffix0代表i后面的前缀和是否有<=1的,对某个?,如果由正变反的时候,suffix0存在,则不行,由反变正,prefix0存在,也不行

为什么呢,。因为反向代表总和值-2或者+2,所以只要有<=1的和值存在,反向可能就会使其变负值,是非法的。。。所以我们这样通过预处理一遍,再一遍扫描下来,即可得出结果

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000000+10;
char str[N];
int num[N];
int prefix[N],suffix[N];
int pre0[N],suf0[N];
int main()
{
    while (scanf("%s",str)!=EOF)
    {
        int len=strlen(str);
        if (len&1){
            printf("None\n");
            continue;
        }
        memset(prefix,0,sizeof(prefix[0])*(len+2));
        memset(suffix,0,sizeof(suffix[0])*(len+2));
        memset(pre0,0,sizeof(pre0[0])*(len+2));
        memset(suf0,0,sizeof(suf0[0])*(len+2));
        for (int i=0;i<len;i++){
            if (str[i]==‘?‘) num[i+1]=0;
            else if (str[i]==‘(‘) num[i+1]=1;
            else num[i+1]=-1;

        }
        bool flag=1;
        for (int i=1;i<=len;i++){
            if (num[i]!=0) prefix[i]=prefix[i-1]+num[i];
            else prefix[i]=prefix[i-1]+1;
            if (prefix[i]<0){
                flag=0;
                break;
            }

        }
        for (int i=len;i>=1;i--){
            if (prefix[i]<=1) pre0[i]=pre0[i+1]+1;
            else pre0[i]=pre0[i+1];
        }
        if(!flag){
            printf("None\n");
            continue;
        }
        for (int i=len;i>=1;i--){
            if (num[i]!=0) suffix[i]=suffix[i+1]-num[i];
            else suffix[i]=suffix[i+1]+1;
            if (suffix[i]<0){
                flag=0;
                break;
            }

        }
        for (int i=1;i<=len;i++){
            if (suffix[i]<=1) suf0[i]=suf0[i-1]+1;
            else suf0[i]=suf0[i-1];
        }
        if (!flag){
            printf("None\n");
            continue;
        }
        int cur=0;
        for (int i=2;i<len;i++){
            //cout<<"Test "<<i<<endl;
            if (num[i]==0){
                //cout<<prefix[i]<<" pre "<<pre0[i]<<endl;
                //cout<<suffix[i]<<" suf "<<suf0[i]<<endl;
                if (prefix[i]>=2 &&pre0[i]==0){
                    if (suffix[i]>=2 && suf0[i]==0) cur++;
                }
            }
        }
        if (cur>1) printf("Many\n");
        else printf("Unique\n");
    }
    return 0;
}

  

HDU 4915 多校5 Parenthese sequence

时间: 2024-08-27 04:31:01

HDU 4915 多校5 Parenthese sequence的相关文章

hdu 4915 Parenthese sequence(模拟)2014多校训练第5场

Parenthese sequence                                                                     Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description bobo found an ancient string. The string contains only t

HDU 4915 Parenthese sequence

HDU 4915 Parenthese sequence 题目链接 题意:给定一个有?的左右括号串,?能替代为'('或')',问括号匹配是否唯一或多种或不可能 思路:先从右往左扫一边,维护一个up, down表示当前位置右边右括号剩余个数的上限和下限,如果维护完后起始位置的下限为0,那么就是可以的,因为为0就代表没有多余的右括号.然后在从左往右扫一遍,和上面一样的处理,只是遇到每个问号的位置时,试一下左括号和右括号,如果都满足,表示这个位置能放左右括号,是多种可能,如果所有?都只有唯一的方法,那

hdu 4915 Parenthese sequence(高效)

题目链接:hdu 4915 Parenthese sequence 题目大意:给定一个序列,由(,),?组成?可以表示(或者),问说有一种.多种或者不存在匹配. 解题思路:从左向右,从右向左,分别维护左括号和右括号可能的情况,区间上下界.如果过程中出现矛盾,则为None,否则要判断唯一解还是多解.枚举每个问号的位置,假设该问号可为左右括号,则有多解. #include <cstdio> #include <cstring> #include <algorithm> us

HDU 4915 Parenthese sequence(瞎搞题)

从左向右扫一遍左括号的最大值,与最小值. 从右向左扫一遍右括号的最大值,与最小值. 比较最大值中的最小数与最小中的最大数看能否有交集,0个,1个或者多个. Parenthese sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 301    Accepted Submission(s): 129 Problem De

HDU 4915 Parenthese sequence _(:зゝ∠)_ 呵呵

呵呵不是我做的 #include <cstdio> #include <cstring> #include <algorithm> const int N = 1000000 + 10; char s[N]; int d[N], num[N]; int main() { while (~scanf("%s", s)) { memset(num, 0, sizeof num); int len = strlen(s); int f = 1, v = 0

hdu 4915 Parenthese sequence (贪心+模拟)

题目大意: 一个序列中有左括号和右括号,还有问号,问号可以任意转换成左右括号. 问这个序列有多少种情况的转变使得这个序列变成合法的括号匹配序列. 思路分析: 首先我们分析一下,如何使得一个序列是合法的括号匹配序列. 我们很容易想到的是用栈模拟匹配过程. 当遇到左括号就进栈,当遇到右括号就让栈顶的左括号出栈. 那么在模拟的过程中,造成这个序列的不合法的原因只有当右括号来的时候,此时的栈已经为空. 这里补充一句,一旦一个序列给定,那么这里面的问号有多少变成左括号,多少变成右括号,是一定的. 看完以上

2014多校联合五(HDU 4911 HDU 4915 HDU 4920)

HDU 4911 Inversion 题意:n个数字  通过k次相邻交换  使得逆序对数最少 思路:如果序列为 XXXABYYY  假设A和B位置互换  易知X和AB.Y和AB的逆序对数不变  换句话说一次交换最多使逆序对减少1  那么只需要求原逆序对数和k进行比较即可 代码: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100100 type

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

HDOJ 4915 Parenthese sequence

Parenthese sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 716    Accepted Submission(s): 335 Problem Description bobo found an ancient string. The string contains only three charate