题意:集合栈计算机。。这是迄今为止我见过的最奇葩的一道题。有一个栈,栈中元素是集合,集合内部的元素还是集合。然后有5种操作,1入栈一个空集,2入栈一个和栈顶一样的集合,3出栈两个集合,入栈他们的并,4出栈两个集合,入栈他们的交,5出栈两个集合,把先出栈的集合加入后出栈的集合中,把结果入栈。每次操作后,输出栈顶集合的大小。
思路:照着紫书上面的代码敲的。其实本来都是空集,只有操作5能最先产生非空集,也就是出现了一个这样的集合,它的元素是一个空集。。。
再来说说那两个cache,实际上是把集合和它的ID双向映射,将不同的集合赋以不同的整数实在是精妙。。
最后是通过这题学到了set_union()和set_intersection()两个函数。还有用到了所谓的“插入迭代器”,这个留给日后学习把。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#define INF 1000000010
#define ll long long
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 100010
using namespace std;
typedef set<int> Set;
map<Set,int> IDcache;
vector<Set> Setcache;
int ID(Set s){
if(IDcache.count(s))return IDcache[s];
Setcache.push_back(s);
return IDcache[s]=Setcache.size()-1;
}
int main(){
int t;
cin>>t;
while(t--){
stack<int> s;
int n;
cin>>n;
string oper;
for(int i=0;i<n;i++){
cin>>oper;
if(oper[0]=='P') s.push(ID(Set()));
else if (oper[0]=='D') s.push(s.top());
else{
Set x1=Setcache[s.top()]; s.pop();
Set x2=Setcache[s.top()]; s.pop();
Set x;
if(oper[0]=='U') set_union(x1.begin(),x1.end(),x2.begin(),x2.end(),inserter(x,x.begin()));
if(oper[0]=='I') set_intersection(x1.begin(),x1.end(),x2.begin(),x2.end(),inserter(x,x.begin()));
if(oper[0]=='A') {
x=x2; x.insert(ID(x1));
}
s.push(ID(x));
}
cout<<Setcache[s.top()].size()<<endl;
}
cout<<"***"<<endl;
}
return 0;
}