1. 程式人生 > 實用技巧 >STL之set

STL之set

\(STL\)大法好

set

閒話不多說,在神奇的\(STL\)庫裡面,有一個非常非常好用而且強的\(STL\)\(set\),內部實現是一棵平衡樹。它神奇的地方就在於可以對插入、刪除、查詢在\(O(logn)\)的時間複雜度內實現,並且相當於維護了一個有序序列。\(set\)內部沒有重複的元素,而\(multiset\)內部可以有重複的元素。下面介紹幾個常用操作。

定義

#include<set>
...
set<int> s;

插入

s.insert(x)表示將值為x的元素插入set中,set會維護有序序列

刪除

s.erase(x)表示刪除值為x的元素

s.erase(it)表示刪除指標為it的元素

s.erase(x);
與
set<int>::iterator it=s.find(x);
if(it!=s.end()) s.erase(it);
等效(multiset中不是

要注意的是,第一個刪除會所有值為\(x\)的元素,而第二個刪除只會刪除一個。對於\(set\)而言,這兩種操作沒有任何區別。但對於\(multiset\),就要看情況選擇刪除全部還是刪除\(1\)個。

查詢

s.find(x)表示查詢值為x的位置,會返回x的指標。如果不存在該元素會返回x.end()

set<int>::iterator it=s.begin();
*it即為最大元素

set<int>::iterator it=--s.end();
*it即為最小元素

二分

s.lower_bound(x)即為查詢大於等於x的第一個數的指標

s.upper_bound(x)即為查詢大於x的第一個數的指標

可以用於查詢前驅後繼

遍歷

set<int> s;
for(int i=1;i<=n;i++) s.insert(a[i]);
for(set<int>::iterator it=s.begin();it!=s.end();it++) cout<<*it<<endl;

學長出的例題

思路

首先前六個操作都是白給。插入刪除,前驅後繼,最大最小,用上述函式即可。而對於操作七,考慮維護一個全域性加變數。每次插入時將插入的\(x\)減去全域性加變數加到\(multiset\)中,然後每次取出的時候再加上全域性加變數輸出就可以了。而且要注意二分求前驅後繼的時候也要查詢\(x-add\)

程式碼

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<set>
#define ll long long
using namespace std;
int q;
ll las,add,op,x;
multiset<ll> s;
int main()
{
	scanf("%d",&q);
	for(int i=1;i<=q;i++){
		scanf("%lld",&op);
		op=op ^ las;
		if(op==1){
			scanf("%lld",&x);
			x-=add;
			s.insert(x);
		}
		if(op==2){
			scanf("%lld",&x);
			multiset<ll>::iterator it=s.find(x-add);
			if(it!=s.end()){
				s.erase(it);
			}
		}
		if(op==3){
			if(!s.size()){
				printf("zay\n");
			}
			else{
				multiset<ll>::iterator it=--s.end();
				las=*it+add;
				printf("%lld\n",las);
			}
		}
		if(op==4){
			if(!s.size()){
				printf("zay\n");
			}
			else{
				multiset<ll>::iterator it=s.begin();
				las=*it+add;
				printf("%lld\n",las);
			}
		}
		if(op==5){
			scanf("%lld",&x);
			multiset<ll>::iterator it=s.lower_bound(x-add);
			if(it==s.begin()){
				printf("cuc\n");
			}
			else{
				it--;
				las=*it+add;
				printf("%lld\n",las);
				
			}
		}
		if(op==6){
			scanf("%lld",&x);
			multiset<ll>::iterator it=s.upper_bound(x-add);
			if(it==s.end()){
				printf("cyc\n");
			}
			else{
				las=*it+add;
				printf("%lld\n",las);
				
			}
		}
		if(op==7){
			scanf("%lld",&x);
			add+=x;
		}
	}
	return 0;
}