题目笔记 UVA12096

  一道综合set,map,stack的STL题目,非常有意思!!

 

 

UVA12096  AC码

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

int n,m;
typedef set<int> jihe;//栈(sta)里存的都是int,而int所代表的集合里也是int
map<jihe,int> quanzhi;
vector<jihe>idinsetout;
stack<int>sta;//栈(sta)里存的都是int(表示集合),因为是集合套集合所以集合里也是int(表示另一集合)


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

int setinidout(jihe c)
{
    if(quanzhi.count(c)) return quanzhi[c];//之前写的是:idinsetout.count(c),被绕晕了
    idinsetout.push_back(c);           //(第一次忘了这个)在vector里新加上一个
    return quanzhi[c]=idinsetout.size()-1;//他的角标就是他的权值(这两步新建集合)
}

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>m;
        for(int j=1;j<=m;j++)
        {
            string s;
            cin>>s;
            if(s[0]=='P') sta.push(setinidout(jihe()));//这里jihe()
            else if(s[0]=='D') sta.push(sta.top());//stack和vector的push操作有区别
            else
            {
                jihe a=idinsetout[sta.top()];
                sta.pop();
                jihe b=idinsetout[sta.top()];
                sta.pop();
                jihe x;
                if(s[0]=='U') set_union (ALL(a),ALL(b),INS(x));
                if(s[0]=='I') set_intersection (ALL(a),ALL(b),INS(x));
                if(s[0]=='A') {x=b;x.insert(setinidout(a));}
                sta.push(setinidout(x));
            }
            cout<<idinsetout[sta.top()].size()<<endl;
        }
        cout<<"***"<<endl;
    }
}

 

 

 

 

梳理

因为第一次思路太乱了错了好几处

所以我重打一遍来捋清思路

 

 

(首先头文件肯定不变)

思路

 题意是集合入栈,我们的思路是用权值代表集合,因此

stack<int>s;

 

 

1.给不同的集合赋不同的权值,并且可以双向导出

但map只能导出集合的权值,所以我们需要另一个容器来导出集合

由于该集合容器不定长,所以可以用vector

map<set<int>,int> idout;
vector<set<int>> lib;

 

 

2.集合套集合,集合本身是能充当元素的(核心)

权值代替集合所以集合的数据类型为int

而不同权值代表的集合可以通过上面的vector得到

typedef set<int>sEt;//这里typedef一个sEt可以简化上面两行代码

map<sEt,int> Map;
vector<sEt>lib;

 

 

 

 

 

双向导出

1.已知集合将其放入map中得到权值,通过函数导出&新建

int sear (sEt a)
{
    if(lib.count(a)) return Map[a];   库里有就直接map返回
    lib.push_back(a);                 没有就push进库
    Map[a]=lib.size()-1;              加一组map,定义vector的序号为权值
}

 

 

2.已知权值直接lib[序号]

 

 

 

 

PUSH

 

s.push(空集权值);

空集权值-->sear(空集);

s.push(sear(sEt()));   //空集入栈

 

 

 

 

 

 

 

DUP

(略)

 

 

 

 

UNION&INTERSECT&ADD

出栈两个集合:

sEt a=lib[s.top()];
s.pop();
sEt b=lib[s.top()];
s.pop();

 

 

并集:   set_union( )

交集:   set_intersection(  )

插入:   集合.insert( )

 //这里可以用宏定义简化

 

 

 

最后把集合x压入栈

s.push(sear(x));

 

 

 

框架

 

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>m;
        
        for(int j=1;j<=m;j++)
        {
            string s;
              
            cin>>s;
            
            if(s[0]=='P').             PUSH操作
           
            else if(s[0]=='D')       DUP操作
            
            else
            {
              UNION&INTERSECT&ADD操作
            }
           
            cout<<栈顶集合大小<<endl;
        }

        cout<<"***"<<endl;

    }
}                    

 

posted @ 2020-03-01 22:47  juuich  阅读(164)  评论(0编辑  收藏  举报