集合栈计算机(The Set Stack Computer,ACM/ICPC NWERC 2006,UVa12096)
对于集合的集合,很难直接表示,因此,为方便起见,为每个不同的集合分配一个不同的ID,每个集合都可以表示成所含集合的ID集合,一个集合就可以表示为一个set
我的理解:
{}:1 {{}} 2
栈中的都是集合,所以也是int类型的
实际进行操作的过程中,可以用map将每种集合和对应的ID关联起来,这样做既可以完成查找ID的任务,还可以同时判定是否出现了新的集合。
用vector作为存储每种集合的cache,这样,每当map中没有相应的ID时,我们就向vector中加入一个set
使用vector将set存储起来的好处是,反过来我们也可以用ID查询到对应的set,这样,通过map和vector,我们实现了set 到ID 的双射。
//聚合栈计算机
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
typedef set<int> Set;
map<Set,int> IDcache;
vector<Set>Setcache;
int ID(Set x)
{
if(IDcache.count(x)) return IDcache[x]; //map中已有key(x),返回对应的value值
Setcache.push_back(x); //map中没有key(x),将其插入vector 中
return IDcache[x]=Setcache.size()-1; //将key(x)存入map中,并将对应的value赋值为在vector中的下标
}
int main()
{
int n,k;
stack<int> s;
cin>>n;
while(n--)
{
cin>>k;
while(k--)
{
string str;
cin>>str;
if(str[0]=='P') s.push(ID(set())); //空集入栈
else if(str[0]='D') s.push(s.top()); //把当前栈顶元素复制一份后再入栈
//剩下的三种操作,涉及到ID
else
{
Set x1 = Setcache[s.top()]; s.pop(); //栈顶第一个集合 (注意:s.top()是一个id)
Set x2 = Setcache[s.top()]; s.pop(); //第二个
Set x; //有一个取并,交的新的集合
if (str[0] == 'U') set_union(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
if (str[0] == 'I') set_intersection(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(x, x.begin()));
if (str[0] == 'A') { x = x2; x.insert(ID(x1)); } //将x1的ID插入到x中
s.push(ID(x)); //合并后的x存入vector中,再将ID压入栈中
}
cout << Setcache[s.top()].size() << endl;
}
}
return 0;
}