The SetStack Computer

原题及翻译

Background from Wikipedia: “Set theory is a branch of mathematics created principally by the German mathematician Georg Cantor at the end of the 19th century.
来自维基百科的背景:“集合论是一个数学分支,主要由19世纪末的德国数学家乔治坎特创立。
Initially controversial, set theory has come to play the role of a foundational theory in modern mathematics, in the sense of a theory invoked to justify assumptions made in mathematics concerning the existence of mathematical objects (such as numbers or functions) and their properties.
最初有争议的是,集合论在现代数学中起到了基础理论的作用,从某种意义上说,集合论被用来证明数学中关于数学对象(如数字或函数)的存在及其性质的假设是合理的。
Formal versions of set theory also have a foundational role to play as specifying a theoretical ideal of mathematical rigor in proofs.”
集理论的正式版本也有一个基础性的作用,作为在证明中指定数学严谨的理论理想。”
Given this importance of sets, being the basis of mathematics, a set of eccentric theorist set off to construct a supercomputer operating on sets instead of numbers.
鉴于集合的重要性,作为数学的基础,一组古怪的理论家着手建造一台以集合而不是数字为基础的超级计算机。
The initial SetStack Alpha is under construction, and they need you to simulate it in order to verify the operation of the prototype.
初始的setstack alpha正在构建中,他们需要您模拟它以验证原型的操作。
The computer operates on a single stack of sets, which is initially empty.
计算机在最初为空的一组集合上运行。
After each operation, the cardinality of the topmost set on the stack is output.
在每次操作之后,将输出堆栈上最顶层集的基数。
The cardinality of a set S is denoted |S| and is the number of elements in S.
集合s的基数用|s|表示,是s中元素的数目。
The instruction set of the SetStack Alpha is PUSH, DUP, UNION, INTERSECT,and ADD.
setstack alpha的指令集是push、dup、union、intersect和add。
• PUSH will push the empty set {} on the stack.
•push将推动堆栈上的空集合。
• DUP will duplicate the topmost set (pop the stack, and then push that set on the stack twice).
•DUP将复制最上面的集合(弹出堆栈,然后将该集合推到堆栈上两次)。
• UNION will pop the stack twice and then push the union of the two sets on the stack.
•UNION将弹出堆栈两次,然后推动堆栈上两组的联合。
• INTERSECT will pop the stack twice and then push the intersection of the two sets on the stack.
•Intersect将弹出堆栈两次,然后推动堆栈上两个集合的交叉点。
• ADD will pop the stack twice, add the first set to the second one, and then push the resulting set on the stack.
•ADD将弹出堆栈两次,将第一组添加到第二组,然后将结果集推送到堆栈上。
For illustration purposes, assume that the topmost element of the stack is
A = {{}, {{}}}
and that the next one is
B = {{}, {{{}}}}
为了便于说明,假设堆栈的最上面的元素是
A = {{}, {{}}}
下一个是
B = {{}, {{{}}}}
For these sets, we have |A| = 2 and |B| = 2. Then:
对于这些集合,我们有a=2和b=2。然后:
• UNION would result in the set {{}, {{}}, {{{}}}}. The output is 3.
•UNION将导致集合{{}, {{}}, {{{}}}}。输出为3。
• INTERSECT would result in the set {{}}. The output is 1.
•INTERSECT将导致集合 {{}}。输出为1。
• ADD would result in the set {{}, {{{}}}, {{},{{}}}}. The output is 3.
•添加将导致集合 {{}, {{{}}}, {{},{{}}}}。输出为3。

Input

An integer 0 ≤ T ≤ 5 on the first line gives the cardinality of the set of test cases.
第一行的整数0≤t≤5给出了一组测试用例的基数。
The first line of each test case contains the number of operations 0 ≤ N ≤ 2000.
每个测试用例的第一行包含操作数0≤n≤2000。
Then follow N lines each containing one of the five commands.
然后N行有五个命令。
It is guaranteed that the SetStack computer can execute all the commands in the sequence without ever popping an empty stack.
它保证了setstack计算机可以按顺序执行所有命令,而不会弹出空堆栈。

Output

For each operation specified in the input, there will be one line of output consisting of a single integer.
对于输入中指定的每个操作,将有一行输出,由单个整数组成。
This integer is the cardinality of the topmost element of the stack after the corresponding command has executed.
这个整数是执行相应命令后堆栈最顶层元素的基数。
After each test case there will be a line with ‘***’ (three asterisks).
每个测试用例之后都会有一行带有“***”(三个星号)。

Sample Input

2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECT

Sample Output

在这里插入图片描述

分析

本题的集合并不是简单的整数集合或者字符集合,而是集合的集合。为了方便起见,此处为每个不同的集合分配一个唯一的ID,则每个集合都可以表示成所包含元素的ID的集合,这样就可以用STL的set来表示了,而整个栈则是一个stack。

代码

#include
#include
#include
#include
#include
#include
#include 

#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
/*
定义两个宏,分别表示“所有的内容”以及“插入迭代器”,具体作用可以从代码中推断出来,
*/

using namespace std;


typedef set<int> Set;
map<Set,int> IDcache;      //把集合映射成ID
vector<Set> Setcache;           //根据ID取集合

//查找给定集合x的ID。如果找不到,分配一个新ID。
int ID(Set x)
{
	if(IDcache.count(x)) return IDcache[x];
	Setcache.push_back(x);      //添加新集合
	return IDcache[x]=Setcache.size()-1;
}

/*
对任意集合s(类型是上面定义的Set),IDcache[s]就是它的ID,
而Setcache[IDcache[s]]就是s本身。
*/

//主程序

int main()
{
    int T;
    cin >> T;
    while (T--) {
        stack<int> s;//题目中的栈
        int n;
        cin >> n;
        for (int i = 0; i < n; i++) {
            string op;
            cin >> op;
            if (op[0] == 'P') s.push(ID(Set()));
            else if (op[0] == 'D') s.push(s.top());
            else {
                Set x1 = Setcache[s.top()]; s.pop();
                Set x2 = Setcache[s.top()]; s.pop();
                Set x;
                if (op[0] == 'U') set_union(ALL(x1), ALL(x2), INS(x));
                if (op[0] == 'I') set_intersection(ALL(x1), ALL(x2), INS(x));
                if (op[0] == 'A') { x = x2; x.insert(ID(x1)); }
                s.push(ID(x));
            }
            cout << Setcache[s.top()].size() << endl;
        }
        cout << "***" << endl;
    }
    return 0;
}

你可能感兴趣的:(Algorithm)