NOIP2017 Day1 T2 70分

说实话,看到这道题的一瞬间就反应过来是道大模拟(真的恶心)
写了一两个小时的样子,最后得了 70 70

本文并不是正解,思路和代码仅供参考

本蒟蒻大概思路就是

一边读一边处理(虽然读完在处理好像也不会超时,习惯问题罢了)
对于 ERR E R R 的情况照着题意判断就行了。

具体实现…

对于 F F E的匹配,用一个计数变量(比如 tot t o t )来模拟就好,遇到 F F ,就让计数器加1tot++),遇到 E E ,就让计数器减1tot--),顺便判断一下,如果计数器为 0 0 且当前有为匹配的E就直接输出 ERR E R R if (tot == 0 && ch == 'E') printf("ERR\n");),不知道怎么做的可以看看这道题

括号匹配

对于重复的字母,用一个 bool b o o l 数组存一下就好了(字母有自己的 ASCII A S C I I 码,可以直接作为下标)但如果只用一个数组的话,退出的操作就不好做了,于是我有用另一个 char c h a r 数组按先后顺序记录每一个循环使用的字母(不知道有没有大佬有更好的做法)used[letter[num]] = 0, letter[num --] = 0;
这样判断重复字母就好办了
if (used[now_letter] == 1) printf("ERR\n");
对于 ERR E R R 的情况,你可以有一堆的方法停下后续的操作,这里我就不详细地分析了(我是直接用一个 bool b o o l 变量判断的)

那如何判断时间复杂度呢

我反正是用gets读入第一行,然后从头挨个处理出行数、复杂度(后文会将为什么要从头)复杂度直接存 n n 的幂,处理时就特判一下,有n就是后面的数字,没有 n n 就直接赋为0 n0=1 n 0 = 1 );

处理完就按行数挨行判断就好while(n--)
每行用gets读入。鉴于前面的错误,也是从头处理。

看了看样例,时间复杂度好像是忽略了小的幂,直接取最大的幂,所以再用一个变量存最大幂。定义一个计数器,从 0 0 开始,对于计数器的处理和前文FE的匹配一样处理。保险起见,我每更新一次就取一次 max m a x (其实是懒得想怎么优化)。

这里要注意一下更新的条件:一定要存在一个 n n ,计数器才加1/减 1 1 (进不进得去一会儿再说),于是如此懒的我又加了一个数组记录哪一次是有n的循环(反正空间不会超)

后来发现样例还是没过…

问题就在于循环进不进得去,由于循环中可能出现 n n ,于是我满篇地找范围,看到了

该数远大于100

这…
远大于是什么鬼…
于是我写了个#define N 101并在心里默默希望数据点不会卡这个上限
这样的话在预处理的时候,处理到 n n ,就直接赋成N就好了。
最后又检查了一下,突然想起来有一种循环叫 F a n n F   a   n   n ,而且它的时间似乎是 O(1) O ( 1 ) ,于是又加了一个特判。
感觉好像也没什么问题…但就是没有A

最后主要注意几个点:
  • 数字可以是多位数 so s o 使用的时候不要用下标直接访问(最开始我样例就死在这里,查了半天没看出来)(用getchar的请默默无视)

  • 一定要自己检查一下,样例过了并不能代表什么,尤其是这种恶心的大模拟

这次样例比较全面,还是可以查出不少错误的
可能有些思路没有讲到的,可以看看我的代码。下面直接上代码(代码比较丑QWQ)

请大佬们帮我看看哪里错了

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

int q;
bool used[205];
char letter_use[205];
bool isreal[205];

inline bool isnumber ( char a ) {
    return ( a >= '0' && a <= '9' );
}

inline bool isn ( char a ) {
    return a == 'n';
}

int main() {
    //freopen("test.in","r",stdin);
    scanf("%d\n",&q);
    while ( q -- ) {
        memset(used,0,sizeof(used));
        /*register*/ int n = 0, mi = 0, real_mi = 0, Time = 0, max_mi = 0, num = 0;
        char oper[20];
        gets(oper);
        bool ishead = 1, isfirst = 0, have_n = 0;
        for ( int i = 0; i < strlen(oper);i ++ ) {
            if ( oper[i] == ' ' && ishead ) {
                ishead = 0;
                isfirst = 1;
                continue;
            }
            if ( oper[i] == 'n' ) have_n = 1;
            if ( ishead && isdigit(oper[i]) ) {
                n = n * 10 + ( oper[i] ^ 48 );
                continue;
            }
            if ( isfirst && isdigit(oper[i]) ) {
                if ( have_n == 0 )
                    mi = 0;
                else
                    mi = mi * 10 + ( oper[i] ^ 48 );
                continue;
            }
        }
        bool tr = 0;
        int Break = -1;
        bool Break_ = 0;
        while ( n -- ) {
            gets(oper);
            if ( ! tr ) {
                char letter;
                char kind;
                int x = 0, y = 0;
                bool issecond = 0;
                bool fn = 0,sn = 0;
                kind = oper[0];
                letter = oper[2];
                for ( int i = 4; i < strlen(oper); i ++ ) {
                    if( oper[i] == ' ' ) {
                        issecond = 1;
                        continue;
                    } 
                    if ( ( ! issecond ) && ( isdigit(oper[i]) || oper[i] == 'n' ) ) {
                        if ( oper[i] == 'n') {
                            x = N;
                            fn = 1;
                        }
                        else
                            x = x * 10 + ( oper[i] ^ 48 );
                    }
                    else if ( issecond && ( isdigit(oper[i]) || oper[i] == 'n' ) ) {
                        if ( oper[i] == 'n') {
                            y = N;
                            sn = 1;
                        }
                        else
                            y = y * 10 + ( oper[i] ^ 48 );
                    }
                }
                if ( kind == 'F' ) {
                    if ( used[letter] == 1 ) {
                        printf("ERR\n");
                        tr = 1;
                        continue;
                    }
                    num++;  
                    Time ++;
                    used[letter] = 1;
                    letter_use[num] = letter;
                    if ( ( ! fn ) && ( ! sn ) ) {
                        if ( x > y ) 
                            ( ! Break_ ) && ( Break = Time, Break_ = 1 );   
                    }
                    if ( ( ! fn ) && sn ) {
                        if ( x > N )
                            ( ! Break_ ) && ( Break = Time, Break_ = 1 );
                        else
                            isreal[num] = 1, real_mi ++,max_mi = max ( max_mi, real_mi );
                    }
                    if ( fn && ( ! sn ) ) {
                        if ( y < N )
                            ( ! Break_ ) && ( Break = Time, Break_ = 1 );
                        else
                            isreal[num] = 1, real_mi ++,max_mi = max ( max_mi, real_mi );
                    }
                }
                if ( kind == 'E' ) {
                    if ( num == 0 ) {
                        printf("ERR\n");
                        tr = 1;
                        continue;
                    }
                    used[letter_use[num]] = 0;
                    real_mi -= isreal[num];
                    isreal[num] = 0;
                    num --;
                    if ( num == 0 ) {
                        real_mi = 0;
                    }
                }
            }
            if ( ! n && ! tr ) {
                if ( Break + 1 )
                    max_mi = Break - 1;
                if ( num )
                    printf("ERR\n");
                else if ( max_mi == mi )
                    printf("Yes\n");
                else
                    printf("No\n");
            }
        }
    }
    return 0;
}

本文并非正解,思路和代码仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值