参考:《21天学通C++》
一、简介
容器 set 和 multiset 让程序员能够快速查找键,键是存储在一维容器中的值
set 和 multiset 之间的区别在于,后者可存储重复的值,而前者只能存储唯一的值
为实现快速搜索,STL set 和 multiset 的内部结构像一棵二叉树,这意味着将元素插入到 set 或 multiset 时将对其进行排序,以提高查找速度
这还意味着不像 vector 那样可以使用其它元素替换给定位置的元素,位于 set 中特定位置的元素不能替换为值不同的新元素
这是因为 set 将把新元素同二叉树中的其它元素进行比较,进而将其放在其它位置
二、基本操作
1、插入
#include <iostream>
#include <set>
using namespace std;
template <typename Container> void PrintContents(const Container & stlContainer);
set<int> Set;
multiset<int> Mset;
int main()
{
Set.insert(60);
Set.insert(-1);
Set.insert(3000);
cout << "Writing the contents of the set to the screen" << endl;
PrintContents(Set);
Mset.insert(Set.begin(), Set.end());
Mset.insert(3000);
cout << "Writing the contents of the multiset to the screen" << endl;
PrintContents(Mset);
cout << "Number of instances of the multiset are : '";
cout << Mset.count(3000) << "'" << endl;
return 0;
}
template <typename Container> void PrintContents(const Container & stlContainer)
{
typename Container::const_iterator itr = stlContainer.begin();
while (itr != stlContainer.end()) {
cout << *itr << endl;
++itr;
}
cout << endl;
}
输出:
Writing the contents of the set to the screen
-1
60
3000
Writing the contents of the multiset to the scre
-1
60
3000
3000
Number of instances of the multiset are : '2'
2、查找
#include <iostream>
#include <set>
using namespace std;
set<int> Set;
int main()
{
Set.insert(43);
Set.insert(78);
Set.insert(-1);
Set.insert(124);
set<int>::const_iterator itr;
for (itr = Set.begin(); itr != Set.end(); ++itr) {
cout << *itr << endl;
}
set<int>::iterator itr_found = Set.find(-1);
if (itr_found != Set.end()) {
cout << "Element " << *itr_found << " found!" << endl;
} else {
cout << "Element not found in set!" << endl;
}
set<int>::iterator itr_nofound = Set.find(12345);
if (itr_nofound != Set.end()) {
cout << "Element " << *itr_nofound << " found!" << endl;
} else {
cout << "Element 12345 not found in set!" << endl;
}
return 0;
}
输出:
-1
43
78
124
Element -1 found!
Element 12345 not found in set!
3、删除
#include <iostream>
#include <set>
using namespace std;
multiset<int> Mset;
int main()
{
Mset.insert(43);
Mset.insert(78);
Mset.insert(78);
Mset.insert(-1);
Mset.insert(124);
multiset<int>::const_iterator itr;
cout << "multiset contains " << Mset.size() << " elements.";
cout << "These are: " << endl;
for (itr = Mset.begin(); itr != Mset.end(); ++itr) {
cout << *itr << endl;
}
cout << "Please enter a number to be erased from the set" << endl;
int num_erase = 0;
cin >> num_erase;
cout << "Erasing " << Mset.count(num_erase) << " instances of value " << num_erase << endl;
Mset.erase(num_erase);
cout << "multiset contains " << Mset.size() << " elements.";
cout << "These are: " << endl;
for (itr = Mset.begin(); itr != Mset.end(); ++itr) {
cout << *itr << endl;
}
return 0;
}
输出:
multiset contains 5 elements.These are:
-1
43
78
78
124
Please enter a number to be erased from the set
78
Erasing 2 instances of value 78
multiset contains 3 elements.These are:
-1
43
124
注意:
函数 erase() 被重载了,可对迭代器(如 find 返回的迭代器)调用 erase() 以删除找到的元素,如下所示
multiset<int>::iterator itr = Mset.find(num_erase);
if (itr != Mset.end()) {
Mset.erase(itr);
} else {
cout << "Element not found!" << endl;
}
同样,erase() 还可用于从 multiset 中删除指定范围内的元素:
multiset<int>::iterator itr = Mset.find(value);
if (itr != Mset.end()) {
Mset.erase(Mset.begin(), itr);
}
上述代码删除从头到值为 value 的所有元素(不包含 value)
要清空 set 和 multiset 的内容,可使用其成员函数 clear()
三、问与答
1、问:如何声明一个其元素按降序排列的整型 set ?
答:set<int> 定义一个整型 set ,这种 set 使用默认排序谓词 std::less<T> 将元素按升序排列
也可将其定义为 set<int, less<int>>
要按降序排列,应将 set 定义为 set<int, greater<int>>
HDU 5700 区间交
参考:http://blog.youkuaiyun.com/tc_to_top/article/details/51476593
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
#include <set>
using namespace std;
#define REP(i, n) for (int i = 0; i < (n); ++i)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> Pair;
const ull mod = 1e9 + 7;
const int INF = 0x7fffffff;
const int maxn = 1e5 + 10;
ll a[maxn], sum[maxn], n, m, k, l, r, maxl = 0;
vector<ll> V[maxn];
multiset<ll> Mset;
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
while (scanf("%I64d %I64d %I64d", &n, &k, &m) != EOF) {
for (ll i = 0; i < n; ++i) {
V[i].clear();
}
Mset.clear();
for (ll i = 1; i <= n; ++i) {
scanf("%I64d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
while (m--) {
scanf("%I64d %I64d", &l, &r);
maxl = max(maxl, l);
V[l].push_back(r);
}
ll ans = 0;
for (ll i = 1; i <= maxl; ++i) {
ll Size = V[i].size();
for (ll j = 0; j < Size; ++j) {
Mset.insert(V[i][j]);
}
while (Mset.size() > k) {
Mset.erase(Mset.begin());
}
if (Mset.size() == k && *Mset.begin() >= i) {
ans = max(ans, sum[*Mset.begin()] - sum[i-1]);
}
}
printf("%I64d\n", ans);
}
return 0;
}
Codeforces 722C Destroying Array
参考:http://www.cnblogs.com/flipped/p/5928466.html
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <bitset>
#include <ctime>
using namespace std;
#define lson low, mid, _id<<1
#define rson mid+1, high, _id<<1|1
typedef long long ll;
typedef pair<ll, ll> Pair;
const ll maxn = 1e5 + 10;
set<Pair> Set;
multiset<ll> Mset;
ll n, p;
ll a[maxn], sum[maxn];
int main()
{
#ifdef __AiR_H
freopen("in.txt", "r", stdin);
#endif // __AiR_H
scanf("%I64d", &n);
for (ll i = 1; i <= n; ++i) {
scanf("%I64d", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
Set.insert(make_pair(n, 1));
Mset.insert(sum[n]);
for (ll i = 1; i <= n; ++i) {
scanf("%I64d", &p);
set<Pair>::iterator itr = Set.lower_bound(make_pair(p, 1));
Mset.erase(Mset.find(sum[itr->first] - sum[itr->second - 1]));
Set.insert(make_pair(p - 1, itr->second));
Mset.insert(sum[p - 1] - sum[itr->second - 1]);
Set.insert(make_pair(itr->first, p + 1));
Mset.insert(sum[itr->first] - sum[p]);
Set.erase(itr);
multiset<ll>::reverse_iterator mitr = Mset.rbegin();
ll ans = *mitr;
printf("%I64d\n", ans);
}
return 0;
}