UVa 12096 The SetStack Computer【STL-stack+其他容器综合】

https://vjudge.net/problem/UVA-12096

stack+其他容器的综合应用

想要用好STL工具写好程序,一定要能将题目中的操作整理抽象出来,一定要思路清晰。

题目分析:

首先题目SetStack computer就告诉我们可以使用set和stack…
本题是对集合的集合操作,也就是说我们的操作是取并集交集等集合操作,我们操作的元素是集合,所以并不是简单实用stack和set就能实现的。
然后根据题目,外层容器用栈stack实现,栈的元素用set实现。
为了实现题目要求的输出栈顶元素大小,也就是栈顶的集合的元素大小,设置了一个栈stack<int> s和vector<Set> Setcache,然后用map<Set,int> IDcache形成他们之间的映射。
就是用vector保存了每个出现过的不一样的集合,然后给其分配一个唯一ID,map用来保存这种映射关系。对于集合的出入栈操作就用集合对应的编号实现了,比如栈{}对应0,{{}}对应1,栈里有两个集合是{} {{}},那么我们的栈中实际存的是0 1。
更加详细的解释:对于每个元素,它有唯一的编号,比如{}对应0,{{}}对应1。之前说过,栈中的每个元素又都是集合,因此如果这个栈的元素是{},对应的Set是空集;如果这个元素是{{}},那么对应的Set是{0},编号为1;如果是{{},{{}}}那么对应的Set是{0,1},这时的Set是一个新Set,它又会有一个自己的编号比如2。
这道题的难点在ADD操作上。

实例分析:

操作栈顶元素个数当前栈的状态(右侧为栈顶)
PUSH0{}
DUP0{} {}
ADD1{{}}
PUSH0{{}} {}
ADD1{{{}}}
DUP1{{{}}} {{{}}}
ADD2{{{}},{{{}}}}
DUP2{{{}},{{{}}}} {{{}},{{{}}}}
UNION2{{{}},{{{}}}}

下面紫书AC代码:
PS:关于一些语法的解释:
Set() 应该是类似于构造函数的用法,生成一个空集
set_union、set_intersection这两个函数的作用和参数就是字面意思。
具体见参考手册搜索对应函数名

typedef set<int> Set;
map<Set,int> IDcache;//把集合映射成ID
vector<Set> Setcache;//根据ID取集合

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

#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())

int main()
{
    stack<int> s; //题目中的栈
    int n,t;
    cin>>t;
    while(t--){
        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、付费专栏及课程。

余额充值