集合栈计算机 stack+map+set

目录

题目描述

代码

思路分析


题目描述

懒的copy英文了,反正大家都是看中文的题目。

有一个专门为了集合运算而设计的“集合栈”计算机。该机器有一个初始为空的栈,并且支持以下操作: 

PUSH:空集“{}”入栈 DUP:把当前栈顶元素复制一份后再入栈 

UNION:出栈两个集合,然后把两者的并集入栈 

INTERSECT:出栈两个集合,然后把二者的交集入栈 

ADD:出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈 每次操作后,输出栈顶集合的大小(即元素个数)。

例如栈顶元素是A={ {}, {{}} }, 下一个元素是B={ {}, {{{}}} },则: UNION操作将得到{ {}, {{}}, {{{}}} },输出3. INTERSECT操作将得到{ {} },输出1 ADD操作将得到{ {}, {{{}}}, { {}, {{}} } },输出3。

样例输入

2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT

样例输出

 0
0
1
0
1
1
2
2
2
***
0
0
1
0
0
***

代码

#include<iostream>
#include<set>
#include<stack>
#include<map>
#include<algorithm>
using namespace std;
int main(){
	stack<set<int>>computer;
	map<set<int>,int>setint;
	int t,o,whole=0;
	string instruction;
	cin>>t;
	while(t--){
		cin>>o;
		while(o--){
			cin>>instruction;
			set<int>temp;
			if(instruction=="PUSH"){temp.clear();}
			else if(instruction=="DUP"){temp=computer.top();}
			else{
				set<int>a=computer.top();
				computer.pop();
				set<int>b=computer.top();
				computer.pop();
				if(instruction=="UNION"){set_union(a.begin(),a.end(),b.begin(),b.end(),inserter(temp,temp.begin()));}
				else if(instruction=="INTERSECT"){set_intersection(a.begin(),a.end(),b.begin(),b.end(),inserter(temp,temp.begin()));}
				else{
					temp=b;
					temp.insert(setint[a]);
				}
			}
			computer.push(temp);
			if(!setint.count(temp))setint[temp]=whole++;
			cout<<computer.top().size()<<endl;
		}
		cout<<"***"<<endl;
	}
}

思路分析

第一次看到题目,觉得没什么问题,然后准备开打,发现 {} 这玩意好像实现有点困难,不行了,看书上代码吧,看得我一脸懵逼,集合和编号,有点烧脑,都是空集,怎么这么多花样?这是怎么从0变1的,最重要的是ADD是怎么实现的?

先说一下书主刘汝佳的思路,对于这个集合的集合,完了还是空集的集合,一堆空集被套,大哥的思路是用一个编号对应一个集合,先是用一个map映射把集合映射成int编号,再用一个vector把所有集合存起来,并让其下标成为集合的编号存进map,定义了一个int型的stack,存储集合的编号。

这个题最关键的地方就是ADD的怎么实现,大哥的思路就是把前一个集合的编号当作元素插入后一个集合里面。

而我的思路则是在此基础上进行了改进,将原代码砍了一半,对于集合的集合,我让他仍是集合,我直接定义了一个set型的stack,这样更加符合题目的认知,就是一个集合栈,而对于集合中的元素集合,就采用int型来表示。

再说一下细节:

对于并集和交集,algorithm库里面有对应打包好的函数可以直接调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MaolinYe(叶茂林)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值