【UVA-12096】解题报告(STL,stack,模拟)

原始题目

题目大意

有一个储存集合的栈,有五种操作。 - 压入空集合 - 将栈顶集合复制再加入栈 - 出栈栈顶两个集合,取交集后入栈 - 出栈栈顶两个集合,取并集后入栈 - 出栈栈顶两个集合,将最顶端的集合加入到次顶的集合中

给出操作,最后输出栈顶集合的元素个数。

解题思路

利用set的数据结构+模拟

  • 集合储存内部集合的编号,空集合就没有编号。
  • 利用map把集合映射成ID,对于每个ADD操作后的新集合查找映射,没有就赋值。
  • 模拟操作最后输出栈顶的size即可。

解题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <string>
#include <sstream>
#include <bits/stdc++.h>
#define rep(i,a,n) for(int i=a;i<n;++i)
#define per(i,a,n) for(int i=n-1;i>=a;--i);
#define ms(x,a) memset((x),a,sizeof((x)))
#define all(x) x.begin(),x.end()
#define ins(x) inserter(x,x.begin())
#define INF 0x3f3f3f3f
#define eps 1e-8
#define fi first
#define e 2.718281828459045235360287471352662497757247093699959574966967627724076630353
#define se second
#define mp make_pair
#define pb push_back
#define np next_permutation
#define gapline cout<<"##======================##"<<endl
using namespace std;
const int maxn=1e5+5;
const int maxl=26;
const int maxm=1e5+5;
typedef long long ll;
typedef unsigned long long ull;
typedef set<int> si;
map <si,int> IDcache; //把集合映射成ID
vector <si> sicache;
int t,n;
// 查找给定集合x的ID。如果找不到,分配一个新的ID
int ID(si x){
if(IDcache.count(x)) return IDcache[x];
sicache.pb(x); //添加新的集合
// cout<<"new="<<sicache.size()-1<<endl;
return IDcache[x]=sicache.size()-1; //返回新的id
// id 都是从 0 开始的
}
stack <int> s;
//建立栈s, 里面储存不同集合的id

int main(){
ios::sync_with_stdio(false);


cin>>t;
while(t--){
while(!s.empty()) s.pop();
sicache.clear();
IDcache.clear();
cin>>n;
string op;
rep(i,0,n){
cin>>op;
if(op[0]=='P') s.push(ID(si())); //调用默认构造函数构造空集合,作为参数传给ID,判断有没有该集合,然后返回id
else if(op[0]=='D') s.push(s.top()); //复制一个添加到栈顶
else{
si x1=sicache[s.top()];s.pop();
si x2=sicache[s.top()];s.pop();
si x;
// cout<<"x1="<<ID(x1)<<" x2="<<ID(x2)<<endl;
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<<sicache[s.top()].size()<<endl;
}
cout<<"***"<<endl;
}

}

收获与反思

  • 紫书说思想很重要