STL中的set——洛谷P5250

 1.作用 / 与优先队列的区别

(1)插入一个元素,自动排序,保证其内部元素有序(升序)。优先队列也可以做到这一点。

(2)支持任意增删一个元素,而优先队列做不到这一点,这是两者其中一个区别。

(3)使用set的前提是唯一键值对,保证了其内部没有重复元素,而优先队列内部同一元素可以有多个,这是两者第二个区别。

2.常用操作

set<int> se;     //以int型为例 默认按键值升序
set<int,greater<int>> se;  //降序排列 

int x;

se.insert(x);	//插入元素x,若x已存在,则什么都不干
se.find(x);		//在q中查找x,返回x的迭代器,若x不存在,则返回指向q尾部的迭代器即 q.end()

se.erase(x);		//删除元素x,若x不存在,则什么都不干
se.erase(it)     //删除集合中地址为it的元素
se.clear();		//清空集合

se.size();		//返回集合se中元素的个数
se.empty();		//判断se是否为空,若是返回1,否则返回0

se.lower_bound(x); //返回一个迭代器,指向第一个键值不小于x的元素,若这个数不存在,则返回se.end()
se.upper_bound(x); //返回一个迭代器,指向第一个键值大于x的元素,若这个数不存在,则返回se.end()

se.begin();		  //返回指向se中第一个元素的迭代器
se.end();		 //返回指向se最后一个元素下一个位置的迭代器 ( 这是一个空指针 ),这个方法很少直接使用,一般是配合其他操作判断某个元素是否存在

3.完整代码

#include<iostream>
#include<algorithm>
#include<set>
using namespace std;

int n,opt,len,w1,w2;
set<int> se;

int main()
{
	int i;
	cin>>n;
	while (n--)
	{
		cin>>opt>>len;
		if (opt==1)
		{
			if (se.find(len)!=se.end())
				cout<<"Already Exist"<<endl;
			else 
				se.insert(len);
		}
		else 
		{
			if (se.empty())
				cout<<"Empty"<<endl;
			else 
			{
				set<int> :: iterator it = se.lower_bound(len),bf=it;
				if (bf!=se.begin())
					bf--;
				if (it!=se.end() && len-(*bf)>(*it)-len)
					bf=it;
				cout<<*bf<<endl;
				se.erase(*bf);
			}
		}
	}
	return 0;
}

4.核心代码片段分析

else                //若是删除操作,且集合不为空
{
    set<int> :: iterator it = se.lower_bound(len),bf=it;

    //也可写成
      set<int> :: iterator it,bf;
      it = se.lower_bound(len);
      bf=it;
	

if (bf!=se.begin())
	bf--;

//若*it不是第一个元素,则bf(before)表示前一个元素
//不能写成bf=it-1,bf和it都是指针类型

if (it!=se.end() && len-(*bf)>(*it)-len)
	bf=it;

//举个例子,集合中元素是1 3 5 7,查找的是 9,根据定义“q.lower_bound(x); //返回一个迭代器,
指向第一个键值不小于x的元素,若这个数不存在,则返回se.end()”,因为不存在,所以返回的是se.end(),
就是7后面的那个空指针,这时不能够对it解引用。

cout<<*bf<<endl;
se.erase(*bf);

//最终输出的是*bf
//千万别忘删除这个元素

#使用lower_bound和upper_bound要注意特判首尾

  • 22
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值