毒瘤模拟题——P3952 时间复杂度
前言
毒瘤题,一遍过,一等奖,才能稳。
另外两个小伙伴 hyh 和 tym 都 WA 过……

正文
题意
我懒不讲(bushi
思路
对于 F ,分情况讨论:
- F x y:$ O(1) $,x 小于 y 时跳过。
- F x n:$ O(n) $。
- F n y:跳过。
- F n n:$ O(1) $。
对于 E ,结束最近的循环,但……
真的这样就行了吗?
F i 1 n
F j 1 n
E
F j 1 n
E
E
最后一个 E 结束的什么?
所以说,我们还是得用 Stack!(毒瘤系数:0.5)
压入 Stack 的是什么呢?
首先,一个显然不够,那么考虑两个。
第一个表示 $ n $ 的几次方了,第二个表示跳不跳过。
那么由栈顶的第一个加上一,栈顶的第二个或一下。
我一开始没判栈顶的第二个的或导致……(毒瘤系数:2.5)
好了,当你自信满满的提交上去时,结果让你大吃一惊:WA。
为什么我能一遍过?还不是我的独家 Debug 法之手造毒瘤小数据!
回去看看:
F i 1 n
E
F i 1 n
E
这组数据就输出了 ERR。
所以,我们不仅要开个 set 存储现在没销毁的变量,还要在压入 Stack 的东西里加上一个变量名,在 E 时也不单单是弹出栈了,还得把那个变量名给 erase 掉……(毒瘤系数:4)
代码
#include <bits/stdc++.h>
using namespace std;
stack<pair<pair<string, int>, bool> > stk;
set<string> st;
int main() {
int t;
cin >> t;
stk.emplace(make_pair(string(""), 0), false);
while (t--) {
st.clear();
int l;
string comp;
cin >> l >> comp;
int expected = 0;
int found = 0;
if (comp == "O(1)") {
found = 0;
} else {
for (int i = 0; i < comp.size(); i++) {
if ('0' <= comp[i] && comp[i] <= '9') {
found = found * 10 + (comp[i] - '0');
}
}
}
bool err = false;
for (int i = 0; i < l; i++) {
string tp;
cin >> tp;
if (tp == "F") {
string nm, sx, sy;
cin >> nm >> sx >> sy;
if (st.count(nm)) {
// puts("Error 1");
err = true;
} else {
st.insert(nm);
}
if (sx == "n" && sy == "n") {
stk.emplace(make_pair(nm, stk.top().first.second + 0), false || stk.top().second);
} else if (sx == "n" && sy != "n") {
stk.emplace(make_pair(nm, stk.top().first.second + 0), true || stk.top().second);
} else if (sx != "n" && sy == "n") {
stk.emplace(make_pair(nm, stk.top().first.second + 1), false || stk.top().second);
} else {
int x = atoi(sx.c_str());
int y = atoi(sy.c_str());
if (x <= y) {
stk.emplace(make_pair(nm, stk.top().first.second + 0), false || stk.top().second);
} else {
stk.emplace(make_pair(nm, stk.top().first.second + 0), true || stk.top().second);
}
}
// printf("%d\n", stk.size());
if (!stk.top().second) {
expected = max(expected, stk.top().first.second);
}
} else {
if (stk.size() > 1) {
st.erase(stk.top().first.first);
stk.pop();
// printf("%d\n", stk.size());
} else {
// puts("Error 2");
err = true;
}
}
}
if (stk.size() > 1) {
// puts("Error 3");
err = true;
while (stk.size() > 1) {
stk.pop();
}
}
if (err) {
puts("ERR");
} else {
if (expected == found) {
puts("Yes");
} else {
puts("No");
}
}
}
return 0;
}
后续
在写代码时,我的状态是这样的:

顺便再说一遍我的超级无敌宇宙第一编代码调试法:
- 手写 5 组毒瘤小数据。
- 写题解,写在 txt 里。
- 边看题解边写代码(我看我自己的题解写代码?!)。
- 测试数据,如果过就提交,如果不过就转到第五行。
- 普通的调试,调到思路已经乱了为止,期间过数据就提交,然后转到第六行。
- 超级调试,给自己讲一遍思路,写注释,目的只有一个:让思路理清楚,让错误水落石出。如果这还不行,放弃这题。
祝你们 RP++ !

浙公网安备 33010602011771号