目录
一. 基本性质
stack是一种栈容器,按照先入后出的规则存储元素。其基本用法如下:
(1)定义与初始化
stack<int> s1;
stack<string> s2;
stack<int> p[10];
(2)基本操作
- s.push(x):入栈
- s.pop():出栈。注意出栈操作只是删除栈顶元素,而并不返回该元素
- s.top():访问栈顶
- s.empty():判断栈空,当栈空时返回true
- s.size():访问栈中的元素个数
二. 例题分析
1. 问题描述
Problem Description
对于一个以集合为元素的栈,初始时栈为空。输入的命令有如下几种:
(1)PUSH:将空集{}压栈
(2)DUP:将栈顶元素复制一份压入栈中
(3)UNION:先进行两次弹栈,将获得的集合A和B取并集,将结果压栈
(4)INTERSECTION:先进行两次弹栈,将获得的集合A和B取交集,将结果压栈
(5)ADD:先进行两次弹栈,将获得的集合A和B中,先出栈的集合(如A先)加入到后出栈的集合,将结果压栈
输出每一步操作后栈顶集合的元素的个数
Sample Input
2
9
PUSH
DUP
ADD
PUSH
ADD
DUP
ADD
DUP
UNION
5
PUSH
PUSH
ADD
PUSH
INTERSECTSample Output
0
0
1
0
1
1
2
2
2
***
0
0
1
0
0
***
2. 题解代码
首先对于集合的集合单纯用容器不好表示无法模拟,但可以给每个集合一个ID,将ID存入大集合就实现了集合的集合。
(1)对于每个小集合,元素唯一,用set<int>来储存小集合元素
(2)对于小集合要给予ID,建立映射关系,采取map<set,int>来建立set->ID
(3)对于所有的小集合,采取vector<set>来储存所有小集合
(4)对于模拟栈操作,用stack<int>才储存ID模拟操作,最后输出vector[stack.top()].size()表示元素个数
注意:这里用到集合的四种算法,求交集并集等算法,将在下节讲述,非常方便快捷!
#include <iostream>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<stack>
#include<algorithm>
using namespace std;
#define ALL(x) x.begin(),x.end()//很迷的宏定义,先看作函数
#define INS(x) inserter(x,x.begin())
typedef set<int> Set;//set小集合
map<Set,int> IDcache;//集合与ID映射
vector<Set> setcache;//按照ID储存集合在大集合
int ID(Set x)//寻找集合ID,有则返回ID,没有创建一个ID并返回
{
if(IDcache.count(x))return IDcache[x];
setcache.push_back(x);
return IDcache[x]=setcache.size()-1;
}
int main()
{
int n,N;
cin>>N;
while(N--)
{
stack<int> s;//定义栈
cin>>n;
while(!s.empty())s.pop();//清空
setcache.clear();
IDcache.clear();
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 x3;
Set x1=setcache[s.top()];//先取出顶部两集合(s.top()是集合ID,然后拿着ID在vector里面寻找集合)
s.pop();
Set x2=setcache[s.top()];
s.pop();
if(op[0]=='U')//并集压入
set_union(ALL(x1),ALL(x2),INS(x3));
else if(op[0]=='I')//交集压入
set_intersection(ALL(x1),ALL(x2),INS(x3));
else if(op[0]=='A')//先出集合插入后出集合压入
{
x3=x2;
x3.insert(ID(x1));//把ID插入X3即可,代表插入一个元素(元素是集合而已)
}
s.push(ID(x3));//结果入栈
}
cout<<setcache[s.top()].size()<<endl;
}
cout<<"***"<<endl;
}
return 0;
}