Skip to the content.

:heavy_check_mark: test/library-checker/DataStructure/SetXor-Min.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/set_xor_min"
#include <bits/stdc++.h>

#include "library/datastructure/BinaryTrie.hpp"

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    BinaryTrie<30, int> BT;
    int q;
    std::cin >> q;
    while (q--) {
        int t, x;
        std::cin >> t >> x;
        if (t <= 1) {
            int c = BT.count(x);
            if (t == 0 and c == 0)
                BT.add(x, +1);
            if (t == 1 and c == 1)
                BT.add(x, -1);
        } else
            std::cout << BT.min(x) << "\n";
    }
}
#line 1 "test/library-checker/DataStructure/SetXor-Min.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/set_xor_min"
#include <bits/stdc++.h>

#line 1 "library/datastructure/BinaryTrie.hpp"
template <int LOG, typename COUNT> class BinaryTrie {
    static_assert(LOG <= 64, "Binary Trie overflow");
    using T = std::conditional_t<LOG <= 32, unsigned int, unsigned long long>;
    struct Node {
        std::array<int, 2> nxt_node;
        COUNT count; //
        Node() : count(0) { std::ranges::fill(nxt_node, -1); }
    };
    std::vector<Node> nodes;
    int &nxt(int now, bool f) { return nodes[now].nxt_node[f]; }
    bool bit(const T &a, int i) const { return (a >> i) & 1; }

  public:
    BinaryTrie() : nodes(1, Node()) {}

    int add(const T &a, COUNT num = 1) {
        int now = 0;
        for (int i = LOG - 1; i >= 0; i--) {
            if (!~nxt(now, bit(a, i))) {
                nxt(now, bit(a, i)) = nodes.size();
                nodes.emplace_back();
            }
            nodes[now].count += num;
            now = nxt(now, bit(a, i));
        }
        nodes[now].count += num;
        return now;
    }

    int node_idx(const T &a) {
        int now = 0;
        for (int i = LOG - 1; i >= 0; i--) {
            if (!~nxt(now, bit(a, i)))
                return -1;
            now = nxt(now, bit(a, i));
        }
        return now;
    }
    COUNT count(const T &a) {
        int id = node_idx(a);
        return (~id ? nodes[id].count : 0);
    }

    COUNT size() { return nodes[0].count; }

    // 数列の各数に xor_add をした後、0-indexed で昇順 k 番目を出力
    T k_th(COUNT k, T xor_add = 0) {
        assert(size() > k);
        T res = 0;
        int now = 0;
        for (int i = LOG - 1; i >= 0; i--) {
            int f = bit(xor_add, i);
            int s = f ^ 1;
            if (nxt(now, f) == -1) {
                now = nxt(now, s);
                res += T{1} << i;
                continue;
            }
            if (nodes[nxt(now, f)].count <= k) {
                k -= nodes[nxt(now, f)].count;
                now = nxt(now, s);
                res += T{1} << i;
            } else
                now = nxt(now, f);
        }
        return res;
    }
    T min(T xor_add = 0) { return k_th(0, xor_add); }
    T max(T xor_add = 0) { return k_th(size() - 1, xor_add); }
};
#line 5 "test/library-checker/DataStructure/SetXor-Min.test.cpp"

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    BinaryTrie<30, int> BT;
    int q;
    std::cin >> q;
    while (q--) {
        int t, x;
        std::cin >> t >> x;
        if (t <= 1) {
            int c = BT.count(x);
            if (t == 0 and c == 0)
                BT.add(x, +1);
            if (t == 1 and c == 1)
                BT.add(x, -1);
        } else
            std::cout << BT.min(x) << "\n";
    }
}
Back to top page