题目
对于一个以集合为元素的栈,初始时栈为空。
输入的命令有如下几种:
PUSH:将空集{}压栈
DUP:将栈顶元素复制一份压入栈中
UNION:先进行两次弹栈,将获得的集合A和B取并集,将结果压栈
INTERSECTION:先进行两次弹栈,将获得的集合A和B取交集,将结果压栈
ADD:先进行两次弹栈,将获得的集合A和B中,先出栈的集合(如A先)加入到后出栈的集合,将结果压栈
要求:输出每一步操作后栈顶集合的元素的个数。
题解
#include <iostream>
#include <set>
#include <stack>
#include <map>
#include <vector>
#include <algorithm>
#include <string>
#include <iterator>
using namespace std;
#define ALL(x) x.begin(), x.end() //迭代器范围
#define INS(x) inserter(x, x.begin()) //插入到x的begin
typedef set<int> Set; //Set是一个int的集合(看作这里的最小单位
map<Set, int> IDcache; //Set -->int(ID,相当于编号)
vector<Set> Setcache; //Set的vec,用于找Set,下标即为入栈顺序
int ID(Set x) //接受一个Set,返回其ID
{
if (IDcache.count(x)) return IDcache[x]; //存在,返回ID
Setcache.push_back(x);
return IDcache[x] = Setcache.size() - 1; //不存在,push后返回ID(即编号,第一个入栈为0)
}
int main()
{
stack<int> s; //题目中的stack
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
string op; //op为对应操作
cin >> op;
if (op[0] == 'P') s.push(ID(Set())); //将一个空集合Set()的ID压栈(相当于把一个空集合压栈)
else if (op[0] == 'D') s.push(s.top()); //将栈顶元素的ID压栈,压栈后,栈顶元素没有ID,栈顶元素即为先前栈顶元素ID
else { //其余操作都有关栈顶元素x1和下面的x2
Set x1 = Setcache[s.top()]; s.pop(); //x1为栈顶元素
Set x2 = Setcache[s.top()]; s.pop(); //x2为栈顶下面的元素
Set x; //x用于计算结果
if (op[0] == 'U') set_union(ALL(x1), ALL(x2), INS(x)); //set_union:STL函数,取并集,x1 x2并集存入x
if (op[0] == 'I') set_intersection(ALL(x1), ALL(x2), INS(x)); //set_intersection:STL函数,取交集,x1 x2交集存入x
if (op[0] == 'A') { //x2赋给x,再插入x1的ID
x = x2;
x.insert(ID(x1));
}
s.push(ID(x));
}
cout << Setcache[s.top()].size() << endl; //在Setcache里按栈顶元素ID找到对应Set,输出其大小
}
return 0;
}
总结
inserter (Container& x, typename Container::iterator it)
适用所有STL容器,插入指定位置int ID(Container x)
,接受一个容器(特别在STL题中,一般将指令编号),返回一个编号,若无,则分配编号——用ID替代内容,是常规操作#define ALL(x) x.begin(), x.end()
值得注意的写法