#include "set.h"
#include <vector>
#include <cstdint>

const int n = 100000007;

Set::Add(int64_t val) {
    int i = (val * 3 + 11) % n;
    while (c[i] != -1 && c[i] != val) {
        i = (i + 17) % n;
    }
    c[i] = val;
}
Set::Remove(int64_t val) {
    int i = (val * 3 + 11) % n;
    while (c[i] != -1 && c[i] != val) {
        i = (i + 17) % n;
    }
    if (c[i] == val) {
        c[i] = -2;
    }
}
bool Set::Contains(int64_t val) const {
    int i = (val * 3 + 11) % n;
    while (c[i] != -1 && c[i] != val) {
        i = (i + 17) % n;
    }
    return (c[i] == val);
}

Set::Set(const std::vector<int64_t>& a) {
    c.assign(n, -1);
    for (int i = 0; i < static_cast<int>(a.size()); i++)
        Add(a[i]);
}

Set Set::Union(const Set& b) const {
    Set new_set;
    for (int i = 0; i < n; i++) {
        if (c[i] >= 0)
            new_set.Add(c[i]);
        if (b.c[i] >= 0)
            new_set.Add(b.c[i]);
    }
    return new_set;
}
Set Set::Intersection(const Set& b) const {
    Set new_set;
    for (int i = 0; i < n; i++) {
        if (c[i] >= 0 && b.Contains(c[i]))
            new_set.Add(c[i]);
    }
    return new_set;
}
Set Set::Difference(const Set& b) const {
    Set new_set;
    for (int i = 0; i < n; i++) {
        if (c[i] >= 0 && !(b.Contains(c[i])))
            new_set.Add(c[i]);
    }
    return new_set;
}
Set Set::SymmetricDifference(const Set& b) const {
    Set new_set;
    for (int i = 0; i < n; i++) {
        if (c[i] >= 0 && !(b.Contains(c[i])))
            new_set.Add(c[i]);
        if (b.c[i] >= 0 && !(Contains(b.c[i])))
            new_set.Add(b.c[i]);
    }
    return new_set;
}

std::vector<int64_t> Set::Data() const {
    std::vector<int64_t> ans;
    for (int i = 0; i < n; i++) {
        if (c[i] >= 0)
            ans.push_back(c[i]);
    }
    return ans;
}