zoukankan      html  css  js  c++  java
  • 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
    ");
                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
    ");
                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
    ");
                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
    ");
            else printf("Unique
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    第06课:GDB 常用命令详解(下)
    第05课:GDB常用命令详解(中)
    第04课:GDB常用命令详解(上)
    第03课:GDB常用的调试命令概览
    第02课:启动GDB调试
    第01课:调试信息与调试原理
    数据库(二)
    数据库笔记(一)
    acedSSGet 翻译
    ObjectARX动态添加AutoCAD传统下拉菜单入门篇(一)
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3902951.html
Copyright © 2011-2022 走看看