set
set 就是数学上的集合,每个元素最多只出现一次,自定义类型也可以 构造 set ,但同样必须定义 “ 小于 ” 运算符。
set 集合是c++ STL库中自带的一个容器,有以下特点:
- 其中的元素都是排好序的
- 其中没有重复的元素
常用的操作:
begin() 返回set 容器的第一个元素的地址
end() 返回set 容器的最后一个元素地址
clear() 删除set 容器中的所有元素
empty() 判断set 容器是否为空
max_size() 返回set 容器能包含的元素最大个数
size() 返回当前set 容器中的元素个数
erase(it) 删除迭代器指针 it 处的元素
insert(a) 插入某个元素
set里面有set_intersection (取集合交集),set_union(取集合并集),set_differnce(取集合差集)等函数。
- 这几个函数的前四个参数一样,只有第五个参数有多重版本。
- set_union(a.begin() , a.end() , b.begin() , b.end() , insert( c.begin() ) ); 前四个参数依次为第一集合的头尾,第二集合的头尾。第五个参数的意思是将集合a和b 取集合并集后的结果存入集合c 中。
- et_union(a.begin() , a.end() , b.begin() , b.end() , ostream_iterator( cout," ")) ;这里第五个参数的意思是将a 和 b 取集合后的结果直接输出,(cout ,“ ”)双引号里面是输出你想用来间隔集合元素的符号或者是空格。
例题:集合栈计算机
有一个专门为了集合运算而设计的“ 集合栈 ” 计算机。该机器有一个初始为空的栈 ,且支持一下操作:
- PUSH: 空集“{}”入栈。
- DUP:把当前栈项元素复制一份后再入栈。
- UNION:出栈两个集合,然后把二者的并集入栈。
- INTERSECT:出栈两个集合,然后把二者的交集入栈。
- ADD: 出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈。
每次操作后,输出栈顶集合的大小(即元素个数)。例如,栈顶元素是A={ {} , {{ }} },下一个元素是B={ { } ,{ { { } } } },则:
UNION操作将得到{ {}, {{ }},{{{ }}} },输出3。
INTERSECT操作将得到{{ }},输出1。
ADD操作将得到{ {} ,{{ { } } } ,{ { },{ { } } } }输出3.
输入不超过2000个操作,并且保证操作均能顺利进行(不需要对空栈执行出栈操作)。
分析
本题的集合并不是简单的整数集合或者是字符串集合,而是集合的集合。为了方便起见,此处为每个不同的集合分配一个唯一 的 ID ,则每个集合都可以表示成元素的ID 的集合,这样就可以用STL 的set 来表示,而整个栈则可以是一个stack.
typedef set<int> Set;
map<Set , int> IDcache; //将集合映射成ID
vector<Set> Setcache; //根据ID 取集合
//查找给定集合x 的ID,如果找不到,分配一个新的ID
int ID(Set x){
if(IDcache.count(x) )
return IDcache[x];
Setcache.push_back(x); //添加一个新的集合
return IDcache[x] = Setcache.size() - 1;
}
对于任意集合s(类型是上面定义的 Set ),IDcache[ s ] 就是它的ID ,而Setcache[ IDcache[ s ] ] 就是s本身。
下面是ALL 和 INS 两个宏:
#define ALL(X) x.begin() ,x.end()
#define INS(s) inserter(x,x.begin())
分别表示“所有的内容”,以及“插入迭代器”。
stack<int> s;
int n;
cin >> n;
for(int i = 0; i < n ; i++){
string op ;
cin >> op ;
if(op[0] == 'P')
s.push( ID(Set()) );
else if(op[0] == 'D')
s.push(s.top()) ;
else{
Set x1 = Setcache[s.top()] ;
s.pop();
Set x2 = Setcache[s.top()] ;
s.pop();
Set x;
if(op[0] == 'U')
set_union (ALL(x1),ALL(x2) ,INS(x));
if(op[0] == 'I')
set_intersection (ALL(x1) ,ALL(x2) ,INS(x));
if(op[0] == 'A'){
x = x2 ;
x.insert(ID(x1));
}
s.push(ID(x));
}
cout<<Setcache[s.top()].size() <<endl;
}
end.