题目大意

用集合模拟计算机操作。每执行完一个操作,输出栈顶的集合大小,操作如下:

  • PUSH:空集合压栈
  • DUP:将栈顶元素再次压栈
  • UNION:依次弹栈得a,b,求并集后压栈
  • INTERSECT:依次弹栈得a,b,求交集后压栈
  • ADD:依次弹栈得a,b,将a作为一个元素加入b中

思路分析

很好的一道题目,关键在于如何设计递归定义的集合的数据结构,只要能判定两个集合异同即可

初步尝试

  • 很自然想到用哈希映射,根据括号和逗号位置,用类似N进制方法计算出一个值,但无奈递归定义的集合个数无限,无法使用此方法
  • 于是想用字符串直接模拟括号和逗号序列,但也过于麻烦

巧妙参考

之前尝试总体思路是对的,均是为了找到一个集合的唯一标识,但不可用函数关系映射方式,这里可用手动构造id方式分配唯一标识,因为递归定义的个数无限,找不到规律且空间有限,只可手动构造,类似malloc申请分配地址。

因此,模仿递归定义设计数据结构,给每个集合分配编号,然后集合中存储已有集合编号,即可实现递归定义

vector<set<int> > setCache; // 哈希表:集合id->集合
map<set<int>, int> setToId; // 映射:集合->id
stack<int>stk; // 栈模拟处理过程,存储集合id

核心实现在于id分配算法,其实现如下,若已有该集合,直接返回id;否则,分配一个新id

int getSetId(const set<int>& _set) { // 获取set对应id,不存在则新分配一个
if (setToId.find(_set) != setToId.end()) return setToId[_set]; // 存在
setCache.push_back(_set); // 不存在则分配
return setToId[_set] = setCache.size() - 1; // id/位置标号
}

至于集合的交并操作可用algorithm中的set_union,set_intersection实现,注意其第五个参数是构造一个存储插入的迭代器,inserter是特殊的插入迭代器,父类为iteratort和t.begin()分别表示存储结果的容器和开始位置

set_union(a.begin(),a.end(),b.begin(),b.end(),inserter(t,t.begin())); // 并集:a U b -> t
set_intersection(a.begin(),a.end(),b.begin(),b.end(),inserter(t,t.begin())); // a交b -> t

注意点

  • set_union和set_intersection的使用,注意第五个参数构造
  • 手动分配id可实现递归定义

AC代码(C++11,手动分配id,集合交并,栈模拟)

#include<bits/stdc++.h>
using namespace std;
vector<set<int> > setCache; // 哈希表:集合id->集合
map<set<int>, int> setToId; // 映射:集合->id
int T, n;
string cmd;
int getSetId(const set<int>& _set) { // 获取set对应id,不存在则新分配一个
if (setToId.find(_set) != setToId.end()) return setToId[_set]; // 存在
setCache.push_back(_set); // 不存在则分配
return setToId[_set] = setCache.size() - 1; // id/位置标号
}
int main() {
cin >>T;
while (T --) {
cin >>n;
stack<int> stk; setCache.clear(); setToId.clear(); // 初始化
while (n --) {
cin >>cmd;
if (cmd == "PUSH") stk.push(getSetId(set<int>())); // 空
else if (cmd == "DUP") stk.push(stk.top()); // 重复
else {
set<int> t, a, b;
a = setCache[stk.top()]; stk.pop();
b = setCache[stk.top()]; stk.pop();
if (cmd == "UNION") set_union(a.begin(),a.end(),b.begin(),b.end(),inserter(t,t.begin()));
if (cmd == "INTERSECT") set_intersection(a.begin(),a.end(),b.begin(),b.end(),inserter(t,t.begin()));
if (cmd == "ADD") t = b, t.insert(setToId[a]);
stk.push(getSetId(t));
}
printf("%d\n", setCache[stk.top()].size());
}
puts("***");
}
return 0;
}

UVA - 12096 :The SetStack Computer的更多相关文章

  1. UVa 12096 (STL) The SetStack Computer

    题意: 有一个集合栈计算机,栈中的元素全部是集合,还有一些相关的操作.输出每次操作后栈顶集合元素的个数. 分析: 这个题感觉有点抽象,集合还能套集合,倒是和题中配的套娃那个图很贴切. 把集合映射成ID ...

  2. 【例题5-5 UVA 12096 】The SetStack Computer

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 用set来解决这个问题. 考虑如何表示 { {{}} }这个集合 我们可以把{}这个集合和一个数字映射->1 然后把1加入到某 ...

  3. UVA.12096 The SetStack Computer ( 好题 栈 STL混合应用)

    UVA.12096 The SetStack Computer ( 好题 栈 STL混合应用) 题意分析 绝对的好题. 先说做完此题的收获: 1.对数据结构又有了宏观的上的认识; 2.熟悉了常用STL ...

  4. uva 12096 The SetStack Computer

    点击打开链接uva 12096 思路: STL模拟 分析: 1 题目给定5种操作,每次输出栈顶集合的元素的个数 2 利用stack和set来模拟,set保存集合的元素.遇到push的时候直接在stac ...

  5. 12096 - The SetStack Computer UVA

    Background from Wikipedia: \Set theory is a branch of mathematics created principally by the German ...

  6. EOJ 1641/UVa The SetStack Computer

    Background from Wikipedia: “Set theory is a branch of mathematics created principally by the German ...

  7. UVa12096.The SetStack Computer

    题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  8. 集合栈计算机(The SetStack Computer, ACM/ICPC NWERC 2006,Uva12096)

    集合栈计算机(The SetStack Computer, ACM/ICPC NWERC 2006,Uva12096) 题目描述 有一个专门为了集合运算而设计的"集合栈"计算机.该 ...

  9. UVA12096 - The SetStack Computer(set + map映射)

    UVA12096 - The SetStack Computer(set + map映射) 题目链接 题目大意:有五个动作: push : 把一个空集合{}放到栈顶. dup : 把栈顶的集合取出来, ...

  10. uva 12096 - The SetStack Computer(集合栈)

    例题5-5 集合栈计算机(The Set Stack Computer,ACM/ICPC NWERC 2006,UVa12096) 有一个专门为了集合运算而设计的"集合栈"计算机. ...

随机推荐

  1. 再学Blazor——组件建造者

    使用 RenderTreeBuilder 创建组件是 Blazor 的一种高级方案.前几篇文中有这样创建组件的示例 builder.Component<MyComponent>().Bui ...

  2. notify为什么会引发超时,notify和notifyAll的区别

    notify为什么会引发超时,notify和notifyAll的区别 每个同步对象都有对应的monitor,首先了解下monitor的内部结构. 1.monitor结构 Owner:指向拥有该同步对象 ...

  3. springboot实现反向代理,动态代理目标地址

    网上找了很多文章,各种照搬,只能自己实现 基于开源项目HTTP-Proxy-Servlet实现 开源项目地址:https://github.com/mitre/HTTP-Proxy-Servlet 1 ...

  4. ConcurrentModificationException日志关键字报警引发的思考

    本文将记录和分析日志中的ConcurrentModificationException关键字报警,还有一些我的思考,希望对大家有帮助. 一.背景 近期,在日常的日志关键字报警分析时,发现我负责的一个电 ...

  5. [CF1849F] XOR Partition

    XOR Partition 题目描述 For a set of integers $ S $ , let's define its cost as the minimum value of $ x \ ...

  6. C++ Qt开发:StatusBar底部状态栏组件

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍QStatus ...

  7. Critical error detected c0000374

    我发现出现上述错误是 free 两次内存 float* dd=new float[2]; delete[] dd; delete[] dd;

  8. Selenium接管已经打开的浏览器并爬取数据

    """ P.S:需要接管现有浏览器 ** 使用步骤: 1.打开浏览器,设置好远程调试端口,并扫描登录淘宝. chrome.exe --remote-debugging-p ...

  9. Java使用HttpUtil.request方法可以发送请求即【Java访问url得到响应数据】

    Java使用HttpUtil.request方法可以发送请求即[Java访问url得到响应数据] 注:这个工具类可以在网上找,也可以自己手写 ,手写的话需要用到以下依赖: <dependency ...

  10. int和String的相互转换