📌  相关文章
📜  查找第k个最小元素并进行点更新的查询:C++中的有序集(1)

📅  最后修改于: 2023-12-03 15:40:25.183000             🧑  作者: Mango

以查找第k个最小元素并进行点更新的查询:C++中的有序集

有序集是C++ STL中的一种数据结构,它能够在插入、删除元素时自动维护元素的大小关系,支持查询排名、查询前驱后继、查询区间等操作。本文将重点介绍有序集支持的查询第k个最小元素并进行点更新的功能。

查询第k个最小元素

假设有一个包含n个元素的有序集,现在需要查询其中第k个最小的元素。有序集提供了两个函数lower_bound和upper_bound,它们分别返回有序集中第一个大于等于x的位置和第一个大于x的位置,结合二分查找即可得到第k个最小元素的值。

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;
int n, a[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    set<int> s(a + 1, a + 1 + n);

    // 查询第k个最小元素
    int k;
    cin >> k;
    auto it = s.begin();
    int l = 1, r = n;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (distance(s.begin(), s.lower_bound(a[1] + mid)) - 1 >= k) r = mid;
        else l = mid + 1;
    }
    cout << *(s.lower_bound(a[1] + l)) << endl;

    return 0;
}

该代码的核心部分是二分查找,其中s.lower_bound(a[1] + mid)返回集合s中第一个大于等于a[1] + mid的位置,distance(s.begin(), it) - 1表示该位置在有序集中的排名。

点更新

有序集支持在O(logn)时间内进行点更新,即修改某个元素的值或者插入一个新元素。

// 修改元素x的值为y
s.erase(x);
s.insert(y);

// 插入元素x
s.insert(x);

下面是一个完整的实例程序,根据输入的操作类型(1为插入,2为修改)来进行相应的操作。

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;
int n, a[N];

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i];
    set<int> s(a + 1, a + 1 + n);

    // 查询第k个最小元素并进行点更新
    int q;
    cin >> q;
    while (q--) {
        int op, x, y;
        cin >> op >> x;
        if (op == 1) {
            s.insert(x);
            n++;
        } else {
            cin >> y;
            s.erase(x);
            s.insert(y);
        }
        // 查询第k个最小元素
        int k;
        cin >> k;
        auto it = s.begin();
        int l = 1, r = n;
        while (l < r) {
            int mid = (l + r) >> 1;
            if (distance(s.begin(), s.lower_bound(*it + mid)) - 1 >= k) r = mid;
            else l = mid + 1;
        }
        cout << *(s.lower_bound(*it + l)) << endl;
    }

    return 0;
}

值得注意的是,在进行插入操作后集合大小需要更新(如上述程序中的n++)。