[Luogu] P3952 时间复杂度
Luogu P3952 时间复杂度
这个题,他又是一个大模拟。考场依然爆炸,我怎么那么水啊
#include <cstdio>
#include <iostream>
#include <cctype>
#include <string>
using namespace std;
int t, l, flr, stp, gvn, rlt, mrlt;
int vis[26], noin[101], inc[101];
char var[101];
string s, ss;
inline int get_int(string ss) { //本函数读入字符串中的数字
if(ss[0] == 'n') return (0x7f);
int x = 0, lent = int(ss.size());
for (int i = 0; i < lent; ++i)
if(isdigit(ss[i])) x = x * 10 + ss[i] - '0';
return x;
}
inline void rest(int now, bool fl) { //读入错误跳出后,该段代码剩余的部分
if(fl) {
cin >> s >> ss;
}
for (int i = now; i <= l; ++i) {
cin >> s;
if(s == "F") {
cin >> s; cin >> s >> ss;
}
}
return ;
}
void solve() {
flr = rlt = mrlt = 0;
cin >> l >> s; //读入行数与预先判断的复杂度
if(int(s.find("n^")) != -1) gvn = get_int(s); //处理复杂度,若是常数以0代替
else gvn = 0;
for (int i = 1; i <= l; ++i) {
cin >> s;
if(s == "F") { //若首字母为循环开始的标志
flr++; //加循环层数
cin >> s; //读入变量名
if(vis[s[0] - 'a'] == stp) { //如果之前变量已经被用过
cout << "ERR\n"; rest(i + 1, true); return ; //错误,跳出
}
vis[s[0] - 'a'] = stp; //将变量标识为已使用
var[flr] = s[0]; //存储该层变量名
if(noin[flr - 1] == stp) noin[flr] = stp; //如果上层未进入,标识该层亦未进入
cin >> s >> ss; //读入开始值与结束值
if(s != ss && !isdigit(ss[0]) && flr > rlt && noin[flr] != stp) {
rlt++; inc[flr] = stp; mrlt = mrlt < rlt ? rlt : mrlt;
} //如果x != y, y = n, 循环层数大于当前最大复杂度, 并且该层可以进入,即使当前最大复杂度加1, 标记该层增加了复杂度, 更新全局最大复杂度的值。
if(s != ss && ((!isdigit(s[0]) && isdigit(ss[0])) || get_int(s) > get_int(ss))) noin[flr] = stp; //如果X != y, 并且x为数字, y = n, 或两者均为数字但x < y的话, 标记该层无法进入。
}
if(s == "E") { //若首字母是循环结束的标志
if(flr - 1 < 0) { //如果层数减一小于零, 即'E'比'F'多
cout << "ERR\n"; rest(i + 1, false); return ; //错误,跳出
}
vis[var[flr] - 'a']--; //当前循环层所用的变量销毁
noin[flr]--; //该层的无法进入标记去掉
if(inc[flr] == stp) { //如果该层增加过复杂度,那么退回
inc[flr]--;
rlt--;
}
flr--; //层数减一
}
}
if(flr != 0) { //如果处理到最后,层数不等于一,即'F'比'E'多
cout << "ERR\n"; return ; //错误,跳出
}
if(gvn == mrlt) {cout << "Yes\n";} //如果实际复杂度等于给定复杂度,输出"Yes"
else cout << "No\n"; //否则输出"No"
return ;
}
int main() {
cin >> t;
while(t--) {
stp++;
solve();
}
return 0;
}