描述

中学数学里集合的元素往往是具体的数字,比如A = {1,2,3},B = {}(空集)等等。但是要特别注意,集合的元素也可以是另一个集合,比如说C = {{}},即说明C有且仅有一个元素——空集B,所以称B是C的子集或者称B是C的元素都是正确的。所谓一个集合的势,就是这个集合的元素个数,一般记为|S|,空集的势为0。在上例中,|A| = 3,|B| = 0,|C| = 1。 鉴于集合论是现代数学的基础理论这一事实,一群异想天开的科学家开始着手建造一台新式的超级计算机——集合堆栈机Alpha,这台机器操作的将是集合而不是数字。不过由于Alpha的竣工之日遥遥无期,科学家们希望你为他们编写一台虚拟机,好让他们检查自己的原型设计是否合理。 Alpha的存储设备只有一个栈,栈的每个单元都只能放置一个集合。一开始,栈是空的,在每个操作结束后,计算机就会输出位于栈顶单元的那个集合的势。Alpha拥有五种不同的指令,分别为:PUSH、DUP、UNION、INTERSECT和ADD,他们的功能如下:

PUSH: 把一个空集{}压入栈;

DUP: 取出位于栈顶单元的集合,复制一遍以后再把两个同样的集合压入栈;

UNION: 取出位于栈顶单元的前两个集合,然后把它们的并集压入栈;

INTERSECT: 取出位于栈顶单元的前两个集合,然后把它们的交集压入栈;

ADD: 取出位于栈顶单元的前两个集合,首先取出的记为S,其次取出的记为T,最后把T∪{S}压入栈;



图为例,可见位于虚拟机堆栈顶端的两个元素是:

A = { {}, {{}} }

B = { {}, {{{}}} }

根据势的定义,我们有|A| = 2 以及 |B| = 2。接下来,

 如果选择UNION操作,结果是{{},{{}},{{{}}},输出3

 如果选择INTERSECT操作,结果是{{}},输出1

 如果选择ADD操作,结果是{{},{{{}}},{{},{{}}}},输出3

分别执行三条指令之后虚拟机就会变成以下三种样子:

输入

文件的第一行只有一个整数n(0≤n≤2000),代表将要执行的指令条数。接下来有n行,每行有包含一条大写的指令,我们保证每条指令都是上述五条指令中的一条,并且虚拟机总是能正确执行完所有的指令。

输出

输出虚拟机的输出结果即可。每行输出一个大于或等于0的整数,代表虚拟机执行该条指令后的输出。选手们务必仔细考量程序的执行效率。

样例输入

9

PUSH

DUP

ADD

PUSH

ADD

DUP

ADD

DUP

UNION

样例2

5

PUSH

PUSH

ADD

PUSH

INTERSECT

样例输出

0

0

1

0

1

1

2

2

2

样例2

0

0

1

0

0

标签

shoi2007


康复训练ing。。。

好吧这题显然不能直接模拟,有一种感觉很优秀的做法是将集合映射成int来乱搞。

然后写了一发感觉取交集与并集有点麻烦。。。

赶快百度了一波惊奇的发现STL中已经有了这个操作心情大好!

于是顺利跑过了。

代码:

#include<bits/stdc++.h>
using namespace std;
struct cmp{
    inline bool operator()(const set<int>&a,const set<int>b){
        if(a.size()!=b.size())return a.size()<b.size();
        set<int>::iterator ita=a.begin(),itb=b.begin();
        while(ita!=a.end()&&*ita==*itb)++ita,++itb;
        return ita==a.end()?false:(*ita<*itb);
    }
};
stack<int>stk;
map<set<int>,int,cmp>mp;
vector<set<int> >vec;
inline int findid(set<int>x){
    if(mp[x])return mp[x];
    vec.push_back(x);
    return mp[x]=vec.size()-1;
}
int main(){
    string s;
    int q;
    scanf("%d",&q);
    while(q--){
        cin>>s;
        if(s[0]=='P')stk.push(findid(set<int>()));
        else if(s[0]=='D')stk.push(stk.top());
        else{
            set<int>x1=vec[stk.top()],tmp;
            stk.pop();
            set<int>x2=vec[stk.top()];
            stk.pop();
            if(s[0]=='U')set_union(x1.begin(),x1.end(),x2.begin(),x2.end(),inserter(tmp,tmp.begin()));
            else if(s[0]=='I')set_intersection(x1.begin(),x1.end(),x2.begin(),x2.end(),inserter(tmp,tmp.begin()));
            else tmp=x2,tmp.insert(findid(x1));
            stk.push(findid(tmp));
        }
        cout<<vec[stk.top()].size()<<'\n';
    }
    return 0;
}

2018.08.28 集合堆栈机(模拟+STL)的更多相关文章

  1. BZOJ1932——[Shoi2007]Setstack 集合堆栈机

    1.题目大意:就是给你一个栈,有一些操作,向栈加入空集,把栈顶的元素复制一遍再加入栈,求栈顶两元素的并集,交集 还有栈的第一个元素和栈顶(将栈顶压缩成一个元素) 2.分析:这个其实不是用hash做的, ...

  2. BZOJ1932 [Shoi2007]Setstack 集合堆栈机

    妈呀...clj大爷太强啦! 原来还有set_union和set_intersection这种东西... 于是只要把栈顶的每个元素hash一下记录到一个vector里去就好了 /*********** ...

  3. 2018.08.28 ali 梯度下降法实现最小二乘

    - 要理解梯度下降和牛顿迭代法的区别 #include<stdio.h> // 1. 线性多维函数原型是 y = f(x1,x2,x3) = a * x1 + b * x2 + c * x ...

  4. 2018.08.28 洛谷P4556 [Vani有约会]雨天的尾巴(树上差分+线段树合并)

    传送门 要求维护每个点上出现次数最多的颜色. 对于每次修改,我们用树上差分的思想,然后线段树合并统计答案就行了. 注意颜色很大需要离散化. 代码: #include<bits/stdc++.h& ...

  5. 2018.08.28 codeforces600E(dsu on tree)

    传送门 一道烂大街的dsu on tree板题. 感觉挺有趣的^_^ 代码真心简单啊! 就是先处理轻儿子,然后处理重儿子,其中处理轻儿子后需要手动消除影响. 代码: #include<bits/ ...

  6. 2018.08.28 洛谷P3803 【模板】多项式乘法(FFT)

    传送门 fft模板题. 终于学会fft了. 这个方法真是神奇! 经过试验发现手写的complex快得多啊! 代码: #include<iostream> #include<cstdi ...

  7. 2018.08.28 洛谷P4360 [CEOI2004]锯木厂选址(斜率优化dp)

    传送门 一道斜率优化dp入门题. 是这样的没错... 我们用dis[i]表示i到第三个锯木厂的距离,sum[i]表示前i棵树的总重量,w[i]为第i棵树的重量,于是发现如果令第一个锯木厂地址为i,第二 ...

  8. 2018.08.28 洛谷P3345 [ZJOI2015]幻想乡战略游戏(点分树)

    传送门 题目就是要求维护带权重心. 因此破题的关键点自然就是带权重心的性质. 这时发现直接找带权重心是O(n)的,考虑优化方案. 发现点分树的树高是logn级别的,并且对于以u为根的树,带权重心要么就 ...

  9. JZOJ5804. 【2018.08.12提高A组模拟】简单的序列

    性质:每个位置的前缀和必须大于0,总和=0.以此dp即可. #include <iostream> #include <cstdio> #include <cstring ...

随机推荐

  1. 前段开发-css-总结

    应用参考https://www.cnblogs.com/alice-bj/p/8972299.html CSS:层叠样式表(Cascading Style Sheets) 1.css的特征 一.css ...

  2. Java LinkList遍历方式

    1.LinkedList的遍历方式 a.一般的for循环(随机访问) int size = list.size(); for (int i=0; i<size; i++) { list.get( ...

  3. ArcGIS 复制要素

    DataManagementTools.General.Copy DataManagementTools.Features.CopyFeatures ConversionTools.ToGeodata ...

  4. WinForm多线程编程与Control.Invoke的应用浅谈

    在WinForm开发中,我们通常不希望当窗体上点了某个按钮执行某个业务的时候,窗体就被卡死了,直到该业务执行完毕后才缓过来.一个最直接的方法便是使用多线程.多线程编程的方式在WinForm开发中必不可 ...

  5. 吴裕雄 实战PYTHON编程(5)

    text = '中华'print(type(text))#<class 'str'>text1 = text.encode('gbk')print(type(text1))#<cla ...

  6. 问题解决Android studio遇到 java.lang.OutOfMemoryError: GC app:transformClassesWithDexForDebug解决方法 以及gradle优化

    http://blog.csdn.net/xiaoxing0828/article/details/52242090

  7. HTTP 和 Socket 区别

    要弄明白 http 和 socket 首先要熟悉网络七层:物 数 网 传 会 表 应,如图1 如图1 HTTP 协议:超文本传输协议,对应于应用层,用于如何封装数据. TCP/UDP 协议:传输控制协 ...

  8. seleniumIDE的实践

    浏览器:1.Firefox setup35.0.12.安装完成后设置菜单栏---安装完浏览器,鼠标定位在浏览器的状态栏,然后点击鼠标右键,点击勾选菜单栏,这时候就有菜单栏出现了 3.关闭浏览器自动更新 ...

  9. 如何使用eclipse搭建maven环境以及常见的错误

    这篇博客适合零基础学习maven,搭建maven以及运行项目,常见的错误,我会在结尾写出说明白,看是否和大家的错误一样,或者文章的括号注释部分也会写出一些注意点. 第一步:就是下载maven,以及配置 ...

  10. discrete

    discrete - 必应词典 美[dɪ'skrit]英[dɪ'skriːt] adj.离散的:分离的:各别的 网络不连续的:分立的:离散型