UVa 12096 集合栈计算机

题目

对于一个以集合为元素的栈,初始时栈为空。

输入的命令有如下几种:

​ 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;
}

总结

  1. inserter (Container& x, typename Container::iterator it)适用所有STL容器,插入指定位置
  2. int ID(Container x),接受一个容器(特别在STL题中,一般将指令编号),返回一个编号,若无,则分配编号——用ID替代内容,是常规操作
  3. #define ALL(x) x.begin(), x.end()值得注意的写法
醉 生 梦 死
原文地址:https://www.cnblogs.com/TuerLueur/p/9650178.html