题意:现有一个栈,有五种操作:
1、PUSH操作:
添加一个空的集合{}到这个栈中
2、DUP操作:
将栈顶复制一份再添加到这个栈中
3、UNION操作:
从栈中弹出两个集合,再将这两个集合的并集加入到栈中
4、INTERSECT操作:
从栈中弹出两个集合,再将这两个集合的交集加入到栈中
5、ADD操作:
从栈中弹出两个集合,并把先弹出的集合添加到后弹出的集合中,再将后弹出的集合添加到栈中。
以上每一次操作完成之后都输出一下栈顶集合的大小,即元素个数,数据输入保证合法。
思路:可以利用STL里的set、map、stack、vector来解决。
我们可以用STL里的set来代替这里的集合,但是我们网stack里存集合的时候不能直接放set,因为这样行不通,这样的话需要set存的类型还是set,这是不允许的。
我们可以为每一个set做一个编号,通过map可以快速找到一个set对应的编号,这样的话,我们再用vector保存所有的set,这样就可以通过编号来解决这题了。
坑点:集合的互异性,即这个题中说的集合中是不能
代码:
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef set < int > SET;
string op;
int n , id;
stack < int > s;
vector < SET > v;
map < SET , int > ID;
inline void init()//初始化
{
id = 0;
v.clear();
ID.clear();
while(!s.empty()) s.pop();
}
int getID(SET a)//通过一个SET直接找到对应的编号
{
if(ID.count(a)) return ID[a];//如果存在
ID[a] = id ++;//对其进行编号
v.push_back(a);//添加到vector中
return id - 1;//返回编号
}
int main(void)
{
int T;
cin >> T;
while(T --)
{
scanf("%d" , &n);
init();
while(n --)
{
cin >> op;
if(op == "PUSH")
{
s.push(getID(SET()));
}
else if(op == "DUP")
{
s.push(s.top());
}
else if(op == "UNION")
{
SET a = v[s.top()] ; s.pop();
SET b = v[s.top()] ; s.pop();
SET c;
//这里采用了c++内置的函数,可以将a和b的并集放入c中
set_union(a.begin() , a.end() , b.begin() , b.end() , inserter(c , c.begin()));
s.push(getID(c));
}
else if(op == "INTERSECT")
{
SET a = v[s.top()] ; s.pop();
SET b = v[s.top()] ; s.pop();
SET c;
//交集
set_intersection(a.begin() , a.end() , b.begin() , b.end() , inserter(c , c.begin()));
s.push(getID(c));
}
else
{
SET a = v[s.top()] ; s.pop();
SET b = v[s.top()] ; s.pop();
b.insert(getID(a));
s.push(getID(b));
}
cout << v[s.top()].size() << endl;
}
printf("***\n");
}
return 0;
}