注意 prev(ms.begin()) 是未定义行为
在 D - Sequence Query 题目中,我提交了以下 WA 代码。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
multiset<ll> ms;
int q;
cin >> q;
while (q--) {
int op;
cin >> op;
ll x, k;
if (op == 1) {
cin >> x;
ms.insert(x);
} else if (op == 2) {
cin >> x >> k;
if (ms.size() == 0) {
cout << -1 << "\n";
continue;
}
auto p = ms.upper_bound(x);
if (p != ms.begin()) {
p = prev(p);
} else { //说明没有合法的
cout << -1 << "\n";
continue;
}
while (k--) {
if (p == ms.begin()) {
break;
}
p = prev(p);
}
cerr << (p == prev(ms.begin()) ? "1: 相等" : "1: 不相等") << endl;
cerr << (p == ms.begin() ? "2: 相等" : "2: 不相等") << endl;
if (p == ms.begin() && k > 0) {
cout << -1 << "\n";
} else {
cout << *p << "\n";
}
} else {
cin >> x >> k;
if (ms.size() == 0) {
cout << -1 << "\n";
continue;
}
--k;
auto p = ms.lower_bound(x);
while (k-- > 0 && p != ms.end()) {
p = next(p);
}
if (p == ms.end()) {
cout << -1 << "\n";
} else {
cout << *p << "\n";
}
}
}
return 0;
}
/*
10
2 14 3
1 6
3 10 2
3 13 3
1 8
2 9 2
1 16
1 2
1 16
1 18
*/
惊奇的发现,prev(ms.begin())
与 ms.begin()
的值是相同的。
所以为了安全起见,不要将迭代器移出 \([begin, end]\) 范围。