#include <iostream>
#include <cstdio>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <algorithm> //set_union set_intersection 的头文件
using namespace std;
int t, n;
string operation; //操作字符
typedef set<int> SET; //简化 set<int>
map<SET, int> IDcache; //将每个不同的集合用int整数表示
vector<SET> SETcache; //存入集合的vector。根据ID取集合
stack<int> element; //定义int堆。先进后出
inline int ID(SET x) //查找给定集合x的ID。如果找不到,分配一个新的ID
{
if(!IDcache.count(x))
{
SETcache.push_back(x);
IDcache[x] = SETcache.size() - 1;
}
return IDcache[x];
}
int main()
{
scanf("%d", & t);
while(t --)
{
scanf("%d", & n);
while(n --)
{
cin >> operation;
SET null;
if(operation == "PUSH")
element.push(ID(null)); //原 element.push(SET())。均为空集
else if(operation == "DUP")
element.push(element.top());
else
{
SET x1 = SETcache[element.top()]; //从里往外 element.top()取栈顶元素(栈存储的是int 即集合的ID)SETcache(序号)即是栈顶集合 栈顶集合也是由int组成
element.pop(); //去掉栈顶元素 为第二次取栈顶元素做准备
SET x2 = SETcache[element.top()];
element.pop();
SET x;
if(operation == "UNION")
set_union(x1.begin(),x1.end(), x2.begin(),x2.end(), inserter(x, x.begin())); //并集
else if(operation == "INTERSECT")
set_intersection(x1.begin(),x1.end(), x2.begin(),x2.end(), inserter(x, x.begin())); //交集
else if(operation == "ADD")
{
x = x2;
x.insert(ID(x1)); //将x1(集合内均是用int序号表示的集合)集合插入x2
}
element.push(ID(x)); //将集合x重新放入栈
}
cout << SETcache[element.top()].size() << endl; //输出栈顶集合大小
}
cout << "***" << endl; //输出格式
}
return 0;
}
题意:有一个专门为了集合运算而设计的“集合栈”计算机。该机器有一个初始为空的栈。支持以下操作:
PUSH:空集“{}”入栈。
DUP:把当前栈顶元素复制一份后再入栈。
UNION:出栈两个集合,然后把二者的并集入栈。
INTERSECT:出栈两个集合,然后把二者的交集入栈。
ADD:出栈两个集合,然后把先出栈的集合加入到后出栈的集合中,把结果入栈。
每次操作,输出栈顶集合的大小(即元素个数)。
题解:其实还是不太清楚SET()。后来改了 SET null。null里没有任何元素 即是空集。与书上的直接ID(SET())相同,不过重新定义一个null更好理解。SETcache(vetor)存的每一个SET均是由集合序号(int)(并非各集合本身)组成的集合。