【Uva12096】map + vector + 栈

1 篇文章 0 订阅

题目链接
解题思路
用map给每个集合分配一个编号,刚好利用了map里的元素不允许重复和count函数可以查询某个元素有没有出现过。用vector把集合存起来,通过编号可以在vector里提取出相应的集合,在栈里操作编号就很方便。
这道题就妙在它是集合的集合,我们为每个不同的集合分配一个ID,那每个集合就可以表示成所包含元素的ID的集合,就可以用set<int> 了。

笔记

  1. set求a与b的并集存在c中:
    set_union(a.begin(), a.end(), b.begin(), b.end(), inserter(c, c.begin() );
    inserter(c,c.begin())为插入迭代器,此函数接受第二个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前。
    交集用 set_intersection
    参考链接

  2. map可太好用了,就是我之前一直不知道它的正确用法【哭泣】
    map<key, value> m;
    它只能从键(key)到值(value)不能从值到键
    比如map<string, int> m; m["july"] = 2;可以,m[2] = "july";就不行

心得
我在紫书上看代码以为我懂的透透的了,但是自己一些编译都过不了。不要抄代码,懂了意思之后自己写写试试。像这种有点乱的题理清楚之后再动手写。

代码

#include <cstdio>
#include <iostream>
#include <iterator>
#include <cstring>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

typedef set<int> Set;
vector<Set> v;
map<Set, int> m;

int getID(Set s)
{
    if (m.count(s)) return m[s];
    v.push_back(s);
    return m[s] = v.size() - 1;
}

stack<int> s;

int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
    	//仔细一想就能发现vector和map不需要清空
        //v.clear();
        //m.clear();
        int n;
        scanf("%d", &n);
        while (n--)
        {
            string op;
            cin >> op;
            if (op[0] == 'P')
            {
                s.push(getID(Set()));
            }
            else if (op[0] == 'D')
            {
                s.push(s.top());
            }
            else
            {
                Set x1 = v[s.top()]; s.pop();
                Set x2 = v[s.top()]; s.pop();
                Set c = Set();
                if (op[0] == 'U')
                {
                    set_union(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(c, c.begin()));
                    s.push(getID(c));
                }
                else if (op[0] == 'I')
                {
                    set_intersection(x1.begin(), x1.end(), x2.begin(), x2.end(), inserter(c, c.begin()));
                    s.push(getID(c));
                }
                else
                {
                    x2.insert(getID(x1));
                    s.push(getID(x2));
                }
            }
            printf("%d\n", v[s.top()].size());
        }
        printf("***\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值