注意 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]\) 范围。

posted @ 2022-02-27 17:07  Nepenthe8  阅读(49)  评论(0编辑  收藏  举报