set 的set_union ,set_intersection 函数

set

set 就是数学上的集合,每个元素最多只出现一次,自定义类型也可以 构造 set ,但同样必须定义 “ 小于 ” 运算符。
set 集合是c++ STL库中自带的一个容器,有以下特点:

  1. 其中的元素都是排好序的
  2. 其中没有重复的元素

常用的操作:
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(取集合差集)等函数。

  1. 这几个函数的前四个参数一样,只有第五个参数有多重版本。
  2. set_union(a.begin() , a.end() , b.begin() , b.end() , insert( c.begin() ) ); 前四个参数依次为第一集合的头尾,第二集合的头尾。第五个参数的意思是将集合a和b 取集合并集后的结果存入集合c 中。
  3. 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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值