11052: 【原1052】二哥学集合论
题目
题目描述
author: yyd 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1052
Description
沈老师给二哥上了一节生动的集合论课,课后老师布置了一道作业题:
实现一个算法来维护一些集合,支持以下三种操作:
\( + \) A B (将集合B并入集合A)
\( - \) A B (将A中的同时出现在A和B中的元素去掉)
\( * \) A B (将A变为A交B)
这题很坑爹,请看清输出要求!,输入的集合中可能包含重复的元素,要注意处理!
Input Format
读入一个数字N,代表你需要维护集合的数目\( N \leq 100 \)
接下来N个数字,代表每个集合中元素的个数\( \leq 200 \) 。 接下来N行,每行包含了第i个集合中的元素每个数字\( 0 \leq x \leq 200 \),会重复!。 一个数\( M \leq 1000 \),表示操作的数目 下面M行,每行一个操作,详见样例。
Output Format
n行,输出最后每个集合的元素,从小到大排序!如果这个集合不是空集,行的最后会有一个空格!如果是空集,直接输出一个空行!
说明
操作过程中每个集合的元素个数不超过200个
Sample Input
4
1 1 1 1
1
2
3
4
3
+ 1 2
- 1 2
* 3 4
Sample Output
1
2
4
FineArtz's solution
/* 二哥学集合论 */
#include <iostream>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
bool a[105][205];
int N, M, n[105], t;
cin >> N;
for (int i = 1; i <= N; ++i)
cin >> n[i];
for (int i = 1; i <= N; ++i){
for (int j = 1; j <= n[i]; ++j){
cin >> t;
a[i][t] = true;
}
}
cin >> M;
char ch;
int x, y;
while (M--){
cin >> ch >> x >> y;
switch(ch){
case '+':
for (int i = 0; i <= 200; ++i){
if (a[y][i])
a[x][i] = true;
}
break;
case '-':
for (int i = 0; i <= 200; ++i){
if (a[y][i])
a[x][i] = false;
}
break;
case '*':
for (int i = 0; i <= 200; ++i){
if (!a[y][i])
a[x][i] = false;
}
break;
}
}
for (int i = 1; i <= N; ++i){
for (int j = 0; j <= 200; ++j)
if (a[i][j]) cout << j << ' ';
cout << '\n';
}
return 0;
}
ligongzzz's solution
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
vector<set<int>> vdata(n);
vector<int> vsize(n);
for (int i = 0; i < n; ++i)
cin >> vsize[i];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < vsize[i]; ++j) {
int temp;
cin >> temp;
vdata[i].insert(temp);
}
}
int m;
cin >> m;
for (; m; --m) {
char op;
int a, b;
cin.get();
cin >> op >> a >> b;
--a;
--b;
if (op == '+') {
vdata[a].insert(vdata[b].begin(), vdata[b].end());
}
else if (op == '-') {
for (auto p = vdata[a].begin(); p != vdata[a].end();) {
if (vdata[b].find(*p) != vdata[b].end()) {
vdata[a].erase(p++);
}
else
++p;
}
}
else {
for (auto p = vdata[a].begin(); p != vdata[a].end();) {
if (vdata[b].find(*p) == vdata[b].end()) {
vdata[a].erase(p++);
}
else
++p;
}
}
}
for (int i = 0; i < n; ++i) {
for (auto p : vdata[i]) {
cout << p << " ";
}
cout << "\n";
}
return 0;
}
yyong119's solution
#include <cstring>
#include <iostream>
using namespace std;
const int MAXN = 100, MAXNUM = 200;
int main() {
ios::sync_with_stdio(false);
int num[MAXN + 1];
bool element[MAXN + 1][MAXNUM + 1];
int n, opnum, tmp;
char op;
memset(num, 0, sizeof(num)); memset(element, false, sizeof(element));
// scanf("%d", &n);
cin >> n;
for (int i = 1; i <= n; ++i)
// scanf("%d", &num[i]);
cin >> num[i];
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= num[i]; ++j) {
// scanf("%d", &tmp);
cin >> tmp;
element[i][tmp] = true;
}
// scanf("%d", &opnum);
cin >> opnum;
while (opnum--) {
int temp1, temp2;
// scanf("%s%d%d", &op, &temp1, &temp2);
cin >> op >> temp1 >> temp2;
if (op == '+') {
for (int i = 0; i <= MAXNUM; ++i)
if (element[temp2][i]) element[temp1][i] = true;
}
else if (op == '-') {
for (int i = 0; i <= MAXNUM; ++i)
if ((element[temp1][i])&&(element[temp2][i])) element[temp1][i] = false;
}
else {
for (int i = 0; i <= MAXNUM; ++i)
if ((element[temp1][i])&&(element[temp2][i])) element[temp1][i] = true;
else element[temp1][i] = false;
}
}
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= MAXNUM; ++j)
// if (element[i][j]) printf("%d ", j);
if (element[i][j]) cout << j << ' ';
// printf("\n");
cout << endl;
}
return 0;
}