通常来说,编译器会试图删除空循环。然而,一些循环并不真的如同看上去那么 “空”,使得编译器无法优化它们。
#ifdef xry111
#define dbg(x) (cerr << __LINE__ << ": " << #x << " = " << (x) << endl)
#else
#define dbg(x)
#endif
// ...
set<int> s;
for (int i = 0; i < q; i++) {
int op, x;
cin >> op >> x;
if (op == 1)
s.insert(x);
else {
auto it = s.lower_bound(x);
cout << (it == s.end() ? -1 : *it) << '\n';
}
// debug
for (auto x: v)
dbg(x);
}
在提交后,由于 xry111
没有定义为宏,dbg(...)
会被展开为空。此时产生了一个空循环:
for (auto x: v) ;
人类很容易看出这是空循环,然而编译器将其展开为
for (auto __begin = v.begin(), __end = v.end(); __begin != __end; ++__begin)
auto x = *it;
而 begin()
、 end()
等又是 STL 中的 114514 行代码实现的,故编译器很难看出这真的是空循环,导致时间复杂度退化成 。
#ifdef DEBUG
和 #endif
包围。