#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;
};