毒瘤模拟题——P3952 时间复杂度

前言

毒瘤题,一遍过,一等奖,才能稳。
另外两个小伙伴 hyh 和 tym 都 WA 过……
image

正文

题意

我懒不讲(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;
}

后续

在写代码时,我的状态是这样的:
image
顺便再说一遍我的超级无敌宇宙第一编代码调试法:

  1. 手写 5 组毒瘤小数据。
  2. 写题解,写在 txt 里。
  3. 边看题解边写代码(我看我自己的题解写代码?!)。
  4. 测试数据,如果过就提交,如果不过就转到第五行。
  5. 普通的调试,调到思路已经乱了为止,期间过数据就提交,然后转到第六行。
  6. 超级调试,给自己讲一遍思路,写注释,目的只有一个:让思路理清楚,让错误水落石出。如果这还不行,放弃这题。
    祝你们 RP++ !
posted @ 2022-08-10 15:35  A-Problem-Solver  阅读(45)  评论(0)    收藏  举报