说实话,看到这道题的一瞬间就反应过来是道大模拟(真的恶心)
写了一两个小时的样子,最后得了
70
70
…
本文并不是正解,思路和代码仅供参考
本蒟蒻大概思路就是
一边读一边处理(虽然读完在处理好像也不会超时,习惯问题罢了)
对于
ERR
E
R
R
的情况照着题意判断就行了。
具体实现…
对于
F
F
和的匹配,用一个计数变量(比如
tot
t
o
t
)来模拟就好,遇到
F
F
,就让计数器加(tot++
),遇到
E
E
,就让计数器减(tot--
),顺便判断一下,如果计数器为
0
0
且当前有为匹配的就直接输出
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
就直接赋为(
n0=1
n
0
=
1
);
处理完就按行数挨行判断就好while(n--)
每行用gets
读入。鉴于前面的错误,也是从头处理。
看了看样例,时间复杂度好像是忽略了小的幂,直接取最大的幂,所以再用一个变量存最大幂。定义一个计数器,从 0 0 开始,对于计数器的处理和前文的匹配一样处理。保险起见,我每更新一次就取一次 max m a x (其实是懒得想怎么优化)。
这里要注意一下更新的条件:一定要存在一个 n n ,计数器才加/减 1 1 (进不进得去一会儿再说),于是如此懒的我又加了一个数组记录哪一次是有的循环(反正空间不会超)
后来发现样例还是没过…
问题就在于循环进不进得去,由于循环中可能出现 n n ,于是我满篇地找范围,看到了
该数远大于
这…
远大于是什么鬼…
于是我写了个#define N 101
并在心里默默希望数据点不会卡这个上限
这样的话在预处理的时候,处理到 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; }
本文并非正解,思路和代码仅供参考