题意
对于一个以集合为元素的栈,初始时栈为空。 输入的命令有如下几种: PUSH:将空集{}压栈 DUP:将栈顶元素复制一份压入栈中 UNION:先进行两次弹栈,将获得的集合A和B取并集,将结果压栈 INTERSECTION:先进行两次弹栈,将获得的集合A和B取交集,将结果压栈 ADD:先进行两次弹栈,将获得的集合A和B中,先出栈的集合(如A先)加入到后出栈的集合,将结果压栈 输出每一步操作后栈顶集合的元素的个数。
输入样例
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<map>
#include<vector>
#include<set>
#include<stack>
#include<string>
#include<algorithm>
using namespace std;
typedef set<int> Set;//集合里面还是集合,但我们把它映射成了数字也就是里面存的都是数字。
map<Set, int> IDcollect;//把集合映射成数字(栈中的)
vector<Set> Setcollect;//用于给集合进行标号,也就是映射数字,对应Set的下标和集合映射。
stack<int> s;
int n,m;
string str;
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
//查找指定集合x的ID
/*
在IDcollect中进行查找,未找到说明还没进行映射,则存入,并返回其下标。
如果找到则,直接返回其下标即可。
*/
int ID(Set x) {
if (!IDcollect.count(x))
{//IDcollect中没有,存入Setcollect,如果有,则最后直接返回即可。
Setcollect.push_back(x);
IDcollect[x] = Setcollect.size() - 1;
}
return IDcollect[x];
}
int main() {
cin >> n;
while (n--) {
cin >> m;
for (int i = 0; i < m; i++) {
cin >> str;
if (str[0] == 'P') {
s.push(ID(Set()));
}
else if (str[0] == 'D') {
s.push(s.top());
}
else {
Set s1 = Setcollect[s.top()];
s.pop();
Set s2 = Setcollect[s.top()];
s.pop();
Set x;
if (str[0] == 'U') {
set_union(ALL(s1), ALL(s2), INS(x));
}
else if(str[0]=='I'){
set_intersection(ALL(s1), ALL(s2), INS(x));
}
else {
x = s2;
x.insert(ID(s1));
}
s.push(ID(x));
}
cout << Setcollect[s.top()].size() << endl;
}
cout << "***" << endl;
}
return 0;
}