Uva12096 集合栈计算机

本文介绍了一种利用STL容器解决复杂集合操作问题的方法,通过为集合分配唯一ID,并使用set、vector和map等容器,实现了集合的高效管理和运算,包括求交集、并集等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果对STL不熟悉的话,这道题确实还挺难的,这道题里综合运用了 STL中的一些容器,如:set,vector,map等,STL中的函数还是挺多的,不断学习,不断掌握吧 。看了看刘汝佳那本书里的解析 ,已经差不多明白了
题目思路 :
本题的集合并不是简单的整数集合或者字符串集合,而是集合的集合。为了方便,我们可以为每个不同的集合分配一个唯一的ID,则每个集合都可以表示成所包含元素的ID集合,这样就可以用STL的set来表示了,而整个栈则是一个stack。
至于题目中要求的求交集、求并集的操作直接用STL中set自带的函数即可。set里面有set_intersection(取集合交集)、set_union(取集合并集)、set_difference(取集合差集)、set_symmetric_difference(取集合对称差集)等函数。
set_union(A.begin(),A.end(),B.begin(),B.end(),inserter( C1 , C1.begin() ) );前四个参数依次是第一的集合的头尾,第二个集合的头尾。第五个参数的意思是将集合A、B取合集后的结果存入集合C中。
set_intersection用法类似。

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

下面贴代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define PI acos(-1.0)
#define seed 31//131,1313
#define MAXV 50010
#define ALL(x) x.begin(),x.end()//这里将set函数中要用的参数定义成宏,方便后面使用
#define INS(x) inserter(x,x.begin())
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
typedef set<int> Set;//每个集合都表示成所包含元素的ID集合
map<Set,int> IDcache;//把集合映射成ID
vector<Set> Setcache; //将所有不同的集合都放进vector中,根据ID取集合。
int ID(Set x){
  if(IDcache.count(x)) return IDcache[x];
  Setcache.push_back(x);  //添加新集合
  return IDcache[x]=Setcache.size()-1;
}
int main()
{
    stack<int>s;
    int t;
    cin>>t;
    while(t--){
        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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值