集合栈计算机(详细解答)UVa12096

news/2024/6/18 21:37:37 标签: 数据结构, 算法, , acm竞赛

题目:
有一个专门为了集合运算而设计的“集合”计算机。该机器有一个初始为空的,并且支持以下操作:
PUSH:空集“{}”入
DUP:把当前顶元素复制一份后再入
UNION:出两个集合,然后把两者的并集入
INTERSECT:出两个集合,然后把二者的交集入
ADD:出两个集合,然后把先出的集合加入到后出的集合中,把结果入
每次操作后,输出顶集合的大小(即元素个数)。例如顶元素是A={ {}, {{}} }, 下一个元素是B={ {}, {{{}}} },则:
UNION操作将得到{ {}, {{}}, {{{}}} },输出3.
INTERSECT操作将得到{ {} },输出1
ADD操作将得到{ {}, {{{}}}, { {}, {{}} } },输出3.
(输入:先输入测试次数,再输入操作次数,再输入具体操作)

输入:
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION

输出:
0
0
1
0
1
1
2
2
2

解题思路:
首先注意他这个集合就是STL中的set,然后模拟,根据它的要求进行做就好了,关键是需要STL中的一些工具以及对set,map,vector的操作熟练。我把这道题要用的方法写在下面包括宏定义。
我在说一下这道题set,map,vector之间的联系。
首先定义了新数据类型Set,然后map的key值为Set,value值为在vector之中的下标,vector中存放Set元素,每次新的Set元素通过ID()方法,将Set存到vector,将对应位置存到map的value中。

题中方法:

set_union(A.begin(),A.end(),B.begin(),B.end(),inserter( C1 , C1.begin() ) );前四个参数依次是第一的集合的头尾,第二个集合的头尾。第五个参数的意思是将集合A、B取合集后的结果存入集合C中。

set_intersection()里面参数和set_union()方法相同,只不过这个是求交集。

inserter(x,x.begin),x表示容器,x.begin()表示迭代器。所以inserter()是一个迭代器返回x.begin()所指向的位置,第二个参数也可以是别的迭代器。

#define ALL(x) x.begin(),x.end() 名字为ALL传入参数x,表示从x的头到x的尾。
#define INS(x) inserter(x,x.begin()) 名字为INS,代表一个迭代器,指向x的开头。

代码:(代码中有详细注释)

#include <bits/stdc++.h>
#define ALL(x)x.begin(),x.end()
#define INS(x)inserter(x,x.begin())
using namespace std;

typedef set<int> Set;//定义新类型Set
map<Set,int> IDcache;//key位Set类型,value为Set的ID
vector<Set> Setcache;//存放Set集合的数组,通过下标ID找到Set

//ID()给传入的Set定义编号(ID)
int ID(Set x)
{
    if(IDcache.count(x))return IDcache[x];//如果map中包含x,则返回x的ID
    Setcache.push_back(x);//添加集合
    return IDcache[x]=Setcache.size()-1;//定义x的ID为vector长度减去1
}


int main()
{

    stack<int>s; //用一个,存放Set的ID
    int n;//n次操作
    cin>>n;
    for(int i=0;i<n;i++)
    {
        string op;//定义操作
        cin>>op;
        if(op[0]=='P')s.push(ID(Set()));//PUSH,添加空集
        else if(op[0]=='D')s.push(s.top());//DUP,将顶元素在添加进
        else{
                //用x1,x2存放顶对应的Set,然后pop()出去顶元素
            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));//合并集合x1,x2,存入x
            if(op[0]=='I') set_intersection(ALL(x1),ALL(x2),INS(x));//取交集存入x
            if(op[0]=='A'){x=x2;x.insert(ID(x1));}//ADD,先将x1插入x2存到x,在将x存入
            s.push(ID(x));
        }
        cout<<Setcache[s.top()].size()<<endl;

    }
    return 0;
}

谢谢观看!
创作不易,多多支持!嘻嘻~~~


http://www.niftyadmin.cn/n/860388.html

相关文章

vue根据权限动态生成路由

vue根据权限动态生成路由 import store from /store // vuex import router from /router // router import axios from ./request // axios // 存放页面信息 const data [// { // 主菜单// path: /okkk, // 页面路径// name: okkk, // 名称// component: () > impo…

团体队列(模拟)

题目: 团体队列题目 思路: 这是一道模拟题,通过map,和两个queue完成,具体细节大家看代码注释,找清楚之间的关系就好。 #include <bits/stdc.h> using namespace std; const int maxt100010;//最多团队数int main() {int t,kcase0;//读入t个团while(scanf("%d"…

丑数-优先队列(详细解答)

题目: 丑数是一些因子只有2,3,5的数。数列1,2,3,4,5,6,8,9,10,12,15……写出了从小到大的前11个丑数&#xff0c;1属于丑数。现在请你编写程序&#xff0c;找出第1500个丑数是什么。 输出&#xff1a;The 1500’th ugly number is <…>.&#xff08;<…>为你找到的…

Unix Is命令(UVa 400)详细解答

题目: 输入正整数n 以及n 个文件名&#xff0c;排序后按列优先的方式左对齐输出。假设最长文件名有M 字符&#xff0c;则最右边有M 字符&#xff0c;其他列都是M2 字符。 题目分析: 有n个文件名,其中最长的文件名有M个字符,一下面输入为例,最长的是Mr._French(共有10个字符),然…

超级楼梯(递推)

题目: 有一楼梯共M级&#xff0c;刚开始时你在第一级&#xff0c;若每次只能跨上一级或二级&#xff0c;要走上第M级&#xff0c;共有多少种走法&#xff1f; 输入: 输入数据首先包含一个整数N&#xff0c;表示测试实例的个数&#xff0c;然后是N行数据&#xff0c;每行包含一…

铺方格(升级版递推)详细解答

题目: 有一个大小是2xN的网格,现在需要用2种规格的骨牌铺满,骨牌的规格分别是2x1和2x2,请计算一共有多少铺设的方法。(从左向右铺) 输入: T组数据,N网格列数 (0<N<50) 输出: 所有方案m Sample Input 1 3 2 Sample Output 1 5 3 解题思路: 这道题和超级楼梯有异曲同工…

LIS最长上升子序列

LIS:从一串数字序列,找出连续递增的子序列,并且要求子序列最长! 举例: 一段序列:1,6,2,3,7,5,9,4,11 最长上升子序列为:1,2,3,7,9,11 那么我们如何通过代码实现呢? 我们需要一个数组f,然后通过f记录每一个数字的最大上升子序列。 初始时每一个f[i]1,因为那怕找不到任意一个子…

LCS最长公共子序列

最长公共子序列:顾名思义从两段序列中选出,其中连续并且相同的子串 举例 a串:1 5 7 9 6 3 b串:1 6 3 2 1 5 最长公共子序列 c串:1 6 3 我们如何实现呢? (假设a串有n个数字,b串有m个数字) 我们需要一个二位数组f,通过这个二维数组存放 f(i,j) f(i,j)含义:表示a串前i个数字,和b串…