C++ set 容器笔记(算法竞赛向)

📌 基本特性

#include <set>
using namespace std;

set<int> S; // 默认升序
set<int, greater<int>> S_desc; // 降序
  • 红黑树实现:自动维护有序性
  • 唯一性:不存储重复元素
  • 操作复杂度
    • 插入/删除/查找:O(log n)
    • 遍历:O(n)

🚀 高频操作

1. 基础操作

S.insert(3);       // 插入元素
S.erase(3);        // 删除元素
S.count(3);        // 存在返回1,否则0
S.find(3);         // 返回迭代器,未找到返回end()
S.size();          // 元素个数
S.empty();         // 判断是否为空
S.clear();         // 清空集合

2. 边界访问(竞赛常用)

set<int> S = {1, 3, 5, 7, 9};

auto it = S.lower_bound(4); // 第一个>=4的元素 → 5
auto it = S.upper_bound(4); // 第一个>4的元素 → 5
auto it = S.upper_bound(9); // 返回end()

// 获取最大/最小值(O(1))
int min_val = *S.begin();
int max_val = *S.rbegin();

3. 范围删除

S.erase(S.lower_bound(3), S.upper_bound(7)); 
// 删除[3,7]区间内所有元素

🔧 特殊技巧

1. 自定义排序(结构体)

struct Point {
    int x, y;
    bool operator<(const Point& p) const {
        return x < p.x || (x == p.x && y < p.y);
    }
};
set<Point> points;

2. 多重集合(允许重复)

#include <set>
multiset<int> MS;
MS.insert(1); 
MS.insert(1); // 允许重复
MS.erase(1);  // 删除所有1
MS.erase(MS.find(1)); // 只删除一个1

3. 快速查找前驱/后继

auto it = S.find(5);
if (it != S.begin()) {
    auto prev_it = prev(it); // 前驱
}
if (next(it) != S.end()) {
    auto next_it = next(it); // 后继
}

⚡️ 性能优化技巧

  1. 预先分配空间(C++11+)

    set<int> S;
    S.reserve(1e5); // 减少插入时的rehash开销
    
  2. 批量插入

    vector<int> v{1,3,5,7};
    S.insert(v.begin(), v.end());
    
  3. emplace替代insert(避免临时对象)

    S.emplace(3); // 比insert(3)更高效
    

🏆 竞赛经典应用

1. 维护动态TopK

set<int> top_k;
while (n--) {
    int x; cin >> x;
    top_k.insert(x);
    if (top_k.size() > K) {
        top_k.erase(top_k.begin());
    }
}

2. 区间查询

// 查询[l,r]区间内的元素个数
int count = distance(S.lower_bound(l), S.upper_bound(r));

3. 离散化处理

set<int> unique_values(arr.begin(), arr.end());
vector<int> mapping(unique_values.begin(), unique_values.end());

💡 常见问题

1. 判断元素存在

// 错误写法(效率低)
if (S.find(3) != S.end()) {...}

// 正确写法
if (S.count(3)) {...}

2. 删除元素陷阱

// 错误:直接删除可能不存在的值
S.erase(100); 

// 安全删除
if (auto it = S.find(100); it != S.end()) {
    S.erase(it);
}

📊 对比其他容器

需求推荐容器原因
需要有序+去重set自动排序,唯一性
允许重复元素multiset保留所有相同元素
只需要判断存在性unordered_set平均O(1)查找
需要快速访问最小/最大setbegin()/rbegin()直接获取

📌 竞赛技巧:遇到"动态维护有序序列"的问题,优先考虑set/multiset

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值