📅  最后修改于: 2023-12-03 15:40:25.183000             🧑  作者: Mango
有序集是C++ STL中的一种数据结构,它能够在插入、删除元素时自动维护元素的大小关系,支持查询排名、查询前驱后继、查询区间等操作。本文将重点介绍有序集支持的查询第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++)。