NOIP2017 时间复杂度
这道题我去年做到爆炸,最后还是爆零了,现在我还是特别慢才写完……
唯一不同就是现在思路比较清晰,但是我的做法比较复杂,代码很长。
我们要处理以下事情:
1.读入程序行数,得到该程序时间复杂度。
这个很简单,我的方法是写一个函数判断一下,然后返回当前时间,如果是常数级就是0.
2.读入程序,判断是否合法。
这一步判断只需要判断变量是否重复即可,不合法直接退出。
3.判断能否进入这次循环。
因为scanf遇到空格会停下,所以我直接使用string来处理。我们要处理的其实就是一个数和n,我写了一个函数进行判断。
4.如果不能进入循环,进入查错状态。
如果不能循环,那么里面的代码没什么用,只能查错。这个还是很舒服的,因为里面就不用考虑能不能进入循环,只考虑是否合法即可。还是自写了一个函数进行判断,只判断变量名重复。之后如果当前栈顶比进来的时候还少,那就从查错状态中返回。
5.能进入循环,进行压栈,更新答案。
这个不用多说了,注意每次的时间也要压入栈中,否则因为我是在线处理的,循环结束的时候你不知道自己应不应该减时间。注意每次压栈都要更新一次当前的最大复杂度。
6.判断循环结束。
这个也很简单,每次把栈还原即可。
7.判断合法。
如果程序结束的时候栈中还有元素或栈中无元素还在往外弹,那就不合法。
注意因为我的方法是直接跳出,所以即使程序不合法也要全部读完。
8.输出结果。
其他注意事项是注意每次保险起见清空数组,之后要记录当前读到哪了,查错和普通状态下都要++。
感觉自己临近NOIP码力仍然很弱……时间不多了。
看一下代码。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<queue> #include<cstring> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') #define pr pair<int,int> #define mp make_pair #define fi first #define sc second using namespace std; typedef long long ll; const int M = 100005; const int N = 10000005; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >='0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } int T,L,sta[1005],top,maxn,maxt,csta[1005],ctop,sen; bool vis[105]; string s,vari,fir,la; void clear() { memset(sta,0,sizeof(sta)),top = 0; memset(csta,0,sizeof(csta)),ctop = 0; memset(vis,0,sizeof(vis)),maxn = sen = 0; } int caltime() { if(s[2] == '1') return 0; int k = 4,cur = 0; while(s[k] >= '0' && s[k] <= '9') cur *= 10,cur += s[k] - '0',k++; return cur; } bool illegal() { return vis[vari[0] - 'a' + 1]; } bool in() { if(fir[0] == 'n') return la[0] == 'n'; int cur = 0,cur1 = 0; rep(i,0,fir.length()-1) cur *= 10,cur += fir[i] - '0'; if(la[0] == 'n') return 1; rep(i,0,la.length()-1) cur1 *= 10,cur1 += la[i] - '0'; return cur < cur1; } bool addtime() { if(fir[0] == 'n') return 0; return la[0] == 'n'; } bool check() { int d = top; while(1) { sen++; cin >> s; if(s[0] == 'F') { cin >> vari >> fir >> la; if(illegal()) return 0; else sta[++top] = vari[0] - 'a' + 1,vis[sta[top]] = 1; } else if(s[0] == 'E') { vis[sta[top]] = 0,sta[top--] = 0; if(top == d - 1) return 1; } } } bool solve(int L,int ctim) { int maxt = maxn = 0; while(sen < L) { sen++,cin >> s; if(s[0] == 'F') { cin >> vari >> fir >> la; if(illegal()) return 0; if(!in()) { sta[++top] = vari[0] - 'a' + 1,vis[sta[top]] = 1; if(!check()) return 0; } else { sta[++top] = vari[0] - 'a' + 1,vis[sta[top]] = 1; csta[++ctop] = maxt,maxt += addtime(); maxn = max(maxn,maxt); } } else { if(!top) return 0; vis[sta[top]] = 0,sta[top--] = 0,maxt = csta[ctop--]; } } if(top) return 0; return 1; } int main() { T = read(); while(T--) { clear(); L = read(),cin >> s; int ctim = caltime(); if(!solve(L,ctim)) printf("ERR\n"); else (maxn == ctim) ? printf("Yes\n") : printf("No\n"); while(sen < L) { cin >> s; if(s[0] == 'F') cin >> vari >> fir >> la; sen++; } } return 0; }
当你意识到,每个上一秒都成为永恒。