先上Vjudge地址:点击这里
题目:
有一个专门为了集合运算而设计的“集合栈”计算机。该机器有一个开始为空的栈并且支持以下操作。
1.PUSH:空集“{}”入栈。
2.DUP:把当前栈顶元素复制一份后在入栈。
3.UNION:出栈两个集合,然后把二者的并集入栈。
4.INTERSECT:出栈两个集合,然后把二者的交集入栈。
5.ADD:出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈。
例如,栈顶元素是A = { {},{{}} },下一个元素是B = { {}, {{{}}} },则:
UNION 操作将得到{ {}, {{}}, {{{}}} },输出3.
INTERSECT 操作将得到{ {} },输出1。
ADD 操作将得到{ {}, {{{}}},{{} , {{}}} },输出3。
输入:
第一行有一个整数T(0<=T<=5)表示有T组测试数据。
每组测试数据有N(0<=N<=2000)次操作,保证操作均能顺利进行(不需要对空栈执行出栈操作)。
输出:
对于输入中指定的每个操作,输出栈顶集合的大小(即元素个数)并换行。
每组测试数据后输出一行“***”。
样例:
Intput
2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT
Output
0
0
1
0
1
1
2
2
2
***
0
0
1
0
0
***
题目分析(依据紫书):
如何模拟题目所述的集合栈呢?大佬们满天飞的stl操作实在是令人折服;
而在本题中要单独说明的一点是,题目中的一切集合都是由一个空集进行操作得来的,故集合内元素的形式绝不仅限于括号或数字,可以延申得更为广泛;
数据结构(重中之重):
说明数据结构的选择之前,我们知道集合内的每个元素都是唯一的,如此便可以给集合内的每个元素赋予序号,在不对元素本身进行操作的情况下以序号代替元素;
例如:{{}}标以序号1,{{},{}}标以序号2,{{{}},{}}标以序号3…等等;
这样我们便可以用set<int> a
储存每个集合,
利用map<set<int>,int> IDcache
储存集合和序号的对应关系;
利用vector<set<int>> Setcache
来进行通过序号获取集合内容;
定义stcak<int> s
存储集合序号的栈;
至此,我们已经可以通过定义的容器和STL的内置函数实现题目中要求的一系列操作了;
算法设计:
就硬模拟呗;
模块设计: 定义与预处理–读入与初始化–模拟–输出–return 0;
代码:
#include<bits/stdc++.h>
using namespace std;
typedef set<int> Set;
map<Set,int> IDcache;
vector<Set> Setcache;
int t,n;
int ID(Set x){
if(IDcache.count(x)) return IDcache[x]; //通过map获取集合标号
Setcache.push_back(x);
return IDcache[x]=Setcache.size()-1; //查找不到就后续标号
}
#define ALL(x) x.begin(),x.end() //蒟蒻不懂的宏,仅仅是套装用
#define INS(x) inserter(x,x.begin())
int main()
{
cin>>t;
while(t--)
{
stack<int> s;
cin>>n;
string order;
for(int i=0;i<n;i++)
{
cin>>order;
if(order=="PUSH") s.push(ID(Set()));
else if(order=="DUP") s.push(s.top());
else{
Set x1=Setcache[s.top()];
s.pop();
Set x2=Setcache[s.top()];
s.pop();
Set x;
if(order=="UNION") set_union (ALL(x1),ALL(x2),INS(x));
if(order=="INTERSECT") set_intersection (ALL(x1),ALL(x2),INS(x));
if(order=="ADD") { x=x2; x.insert(ID(x1));}
s.push(ID(x));
}
cout<<Setcache[s.top()].size()<<endl;
}
cout<<"***"<<endl;
}
return 0;
}
要点与细节总结:
- 关于代码中的
set_union
与set_intersection
是STL的内置函数,存于头文件#include<set>
,uinon为取并集,intersection为取交集;使用详情参考这里; - 膜拜大佬STL的使用;