#pragma once
#include <cstdint>
#include <algorithm>
#include <vector>
class Set {
public:
Set() {}
explicit Set(const std::vector<int64_t>& other) {
for (auto i : other) {
this->Add(i);
}
}
Set Union(const Set& other) const {
Set a(v);
for (auto i : other.Data()) {
a.Add(i);
}
return a;
}
Set Intersection(const Set& other) const {
Set a;
int64_t it1 = 0, it2 = 0;
while (it1 != v.size() && it2 != other.Data().size()) {
if (v[it1] == other.Data()[it2]) {
a.Add(v[it1]);
it1++;
it2++;
} else {
v[it1] > other.Data()[it2] ? it2++ : it1++;
}
}
return a;
}
Set Difference(const Set& other) const {
Set a(v);
for (auto i : other.Data()) {
a.Remove(other.Data()[i]);
}
return a;
}
Set SymmetricDifference(const Set& other) const {
Set a;
int64_t it1 = 0, it2 = 0;
while (it1 != v.size() || it2 != other.Data().size()) {
if (v[it1] != other.Data()[it2]) {
if (it2 != other.Data().size()) {
if (v[it1] > other.Data()[it2])
a.Add(other.Data()[it2++]);
else if (it1 != v.size())
a.Add(v[it1++]);
} else {
a.Add(v[it1++]);
}
} else {
it1++;
it2++;
}
}
return a;
}
void Add(int64_t num) {
if (this->Contains(num)) return;
v.push_back(num);
sort(v.begin(), v.end());
}
void Remove(int64_t num) {
if (!this->Contains(num)) return;
for (int i = 0; i < v.size(); i++) {
if (v[i] == num) v.erase(v.begin() + i);
}
}
bool Contains(int64_t num) const {
if (find(v.begin(), v.end(), num) == v.end()) return false;
return true;
}
std::vector<int64_t> Data() const {
return v;
}
private:
std::vector<int64_t> v;
};