前言:容器包括
顺序容器(如vector,队列deque,list,array,string等,特点是具备快速访问容器元素的能力)
关联式容器(如set,map等,特点是支持高效的关键字查找)
1,特点
1,set中元素排列有序
2,每个元素特定且唯一,不会重复出现
2,常用函数
set<int>s;//默认升序排列
set<int, greater<int>>s1; //降序排列
int x = 1;
s.insert(x);//插入
s.erase(x);//删除x,有返回1,没有返回0
s.clear();//清空
s.empty();//元素为空返回1,否则为0
s.count(x);//count本来是原来计数,但是set要么存在要么没有(即1或者0),那么可以利用这个特点快速判断是否存在(真或者假)
3,常用迭代器
set<int>s;//默认升序排列
int x = 1;
s.begin();//第一个元素
s.rbegin();//最后一个元素
s.end();//最后一个元素的下一个位置(相当于\0)
s.rend();//第一个元素的上一个位置
s.lower_bound(x);//返回元素中第一个不小于(>=)x的元素的迭代器(就是这个元素的值)
s.upper_bound(x);//返回第一个大于(>)x的元素的迭代器
s.find(x);//如果元素中有x,返回其迭代器(即x),没有,返回end()的迭代器
//find的使用方法
if (s.find(x) != s.end())//返回值不是end,那就是存在
{
cout << *s.find(x);//使用迭代器要注意,要用指针操作,才能表示其数值
}
4,常用遍历方法
因为关联式容器无法像顺序容器那样快速访问,所以必须给他指定顺序(使用迭代器访问)
//从头访问到尾写法
for (auto it = s.begin(); it != s.end(); ++it) //s使用auto自动识别比较简洁
{
cout << *it << endl;
}
//***************另外一种等价的简洁写法*******
for (auto &k : s)cout << k << endl;
//遍历[x,y]这个闭区间(其余同理)
int x, y;
for (auto it = s.lower_bound(x); it != s.lower_bound(y); ++it)cout << *it << endl;
5,模板题:C. Set Construction
思想:大的集合包含小的集合,又因为集合不能重复,毫无疑问用set来继承子代比较方便(不会重复),因为有n个集合,所以一开始每个集合各自赋值一个(保证大集合始终有一个元素是其子集没有的),然后我们遍历i*j,父代继承子代集合即可
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
char a[200][200];
void mymin()
{
map<int, set<int> >mp;//用map存放第i组的set
memset(a, 0, sizeof(a));
int n;
cin >> n;
for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)cin >> a[i][j];
for (int i = 1; i <= n; ++i)mp[i].insert(i);//每个集合初始赋值一个元素
for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)
if (a[i][j] == '1')for (auto &k : mp[i])mp[j].insert(k);//=‘1’,说明存在父子关系,继承(遍历子代mp[i]的元素存入mp[j]里面
for (int i = 1; i <= n; ++i)
{
cout << (int)mp[i].size();
for (auto &k : mp[i])cout << " " << k;
cout << endl;
}
}
int main()
{
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
ll t;
cin >> t;
while (t--)
{
mymin();
}
system("pause");
return 0;
}