毒瘤大模拟题!
看到这种又是字符串又是模拟的题目就很伤,很多的地方都考验细节。
看到这种处理循环的方式是后进先出,自然想到了用栈来模拟。
但是最主要的思路是怎么算复杂度?
其实说白了也简单:一个循环的复杂度 = 这个循环本身的复杂度 + 在里面嵌套的最大的复杂度
这里的每一个循环变量都是不重复的,如果重复直接判ERR。
那么我们就可以用一个循环变量来代表一个循环,利用他们记录一个循环本身的复杂度和实际的复杂度。
如何计算一个循环的本身时间复杂度?
如果x不是\(n\),y是\(n\),这个循环是\(O(n)\)的。
如果x和y都是\(n\),这个循环是\(O(1)\)的。
如果x是\(n\)而y不是\(n\),那么这个循环不执行。
如果x和y都是数字,比较他们的大小,当且仅当\(x \leq y\)时有\(O(1)\)的复杂度,否则不执行。
这里有一个很重要的思想:如果一个循环不执行,那么我就不去考虑这个循环内的任何时间复杂度!顶多看看会不会有语法错误就好了。
而有一个挺特殊的情况:如果任何循环都不执行的话是\(O(1)\)的。这个在样例已经跟你说了。
维护的时候直接用一个数字来维护,意义是\(n\)的几次方,所以\(O(1)\)用0来代替,不执行的情况我用-1来搞。
ERR总共有3种情况:
F太多。这个在最后看看栈是不是空的就可以了。
E太多。那么这个时候会发生栈下溢,特判解决。
变量重名。开一个used数组判一下就可以了。
总体来说不难,但是需要你有正确的思路!!!
这个故事告诉我们:写大模拟的时候一定要先想清楚所有的情况再写!
说人话就是:
\[\huge{Think \quad twice, code \quad once!}\]
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<sstream>
#include<stack>
using namespace std;
string str[105];
bool used[30];
int source[30], comp[30];
int id(char x)
{
return x - 'a' + 1;
}
int to_int(string x)
{
int len = x.length(), ans = 0;
for(int i = 0; i < len; i++) ans = ans * 10 + x[i] - '0';
return ans;
}
int calc(string x, string y)
{
bool flag1 = (x[0] != 'n'), flag2 = (y[0] != 'n');// is a number
if(flag1)
{
if(flag2)
{
int num1 = to_int(x), num_2 = to_int(y);
if(num1 <= num_2) return 0;
else return -1;
}
else return 1;
}
else
{
if(flag2) return -1;
else return 0;
}
}
int solve(int len, int expected)
{
memset(used, false, sizeof used);
memset(source, 0, sizeof source);
memset(comp, 0, sizeof comp);
stack<char> sta;
int ans = 0;
for(int i = 1; i <= len; i++)
{
stringstream ss(str[i]);
string opt, name, x, y;
ss >> opt;
if(opt[0] == 'F')
{
ss >> name >> x >> y;
if(used[id(name[0])]) return 3;// ERR
used[id(name[0])] = true;
comp[id(name[0])] = source[id(name[0])] = calc(x, y);
sta.push(name[0]);
}
else if(opt[0] == 'E')
{
if(sta.empty()) return 3;// ERR
char name = sta.top(); sta.pop();
used[id(name)] = false;
if(sta.empty())
{
ans = std::max(ans, comp[id(name)]);
}
else
{
if(source[id(sta.top())] != -1) comp[id(sta.top())] = std::max(comp[id(sta.top())], source[id(sta.top())] + comp[id(name)]);
}
}
}
if(!sta.empty()) return 3;// ERR
if(ans == expected) return 1;
else return 2;
}
void print(int res)
{
if(res == 1) cout << "Yes\n";
else if(res == 2) cout << "No\n";
else if(res == 3) cout << "ERR\n";
else cout << "I AK NOIP!\n";
}
int main()
{
int T; cin >> T;
while(T--)
{
int len, expected; string temp;
cin >> len >> temp;
if(temp[2] == '1') expected = 0;
else
{
stringstream ss(temp.substr(4));
ss >> expected;
}
for(int i = 0; i <= len; i++) getline(cin, str[i]);
int res = solve(len, expected);
print(res);
}
return 0;
}