一道综合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; } }