This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "structure/others/binary-trie.hpp"
#pragma once
#include <bits/stdc++.h>
#include <cstdint>
#include "./structure/others/trie.hpp"
using namespace std;
struct Node : public TrieNode {
int cnt;
Node(int char_size) : TrieNode(char_size) {
cnt = 0;
}
};
struct BinaryTrie : public Trie<Node> {
BinaryTrie() : Trie(2, '0') {}
explicit BinaryTrie(int node_size) : Trie(2, '0', node_size) {}
void add_number(uint64_t x, int max_bit = 63) {
int now = root;
for (int i = max_bit; i >= 0; i--) {
int b = (x >> i) & 1;
if (nodes[now].nxt[b] == -1) {
nodes[now].nxt[b] = new_node();
}
now = nodes[now].nxt[b];
nodes[now].cnt++;
}
}
void erase_number(uint64_t x, int max_bit = 63) {
int now = root;
for (int i = max_bit; i >= 0; i--) {
int b = (x >> i) & 1;
now = nodes[now].nxt[b];
nodes[now].cnt--;
}
}
uint64_t max_xor(uint64_t x, int max_bit = 63) {
int now = root;
uint64_t ans = 0;
for (int i = max_bit; i >= 0; i--) {
int b = (x >> i) & 1;
int want = b ^ 1;
if (nodes[now].nxt[want] != -1 && nodes[nodes[now].nxt[want]].cnt > 0) {
ans |= (1ULL << i);
now = nodes[now].nxt[want];
} else if (nodes[now].nxt[b] != -1 && nodes[nodes[now].nxt[b]].cnt > 0) {
now = nodes[now].nxt[b];
} else {
break;
}
}
return ans;
}
};
#line 2 "structure/others/binary-trie.hpp"
#include <bits/stdc++.h>
#line 5 "structure/others/binary-trie.hpp"
#line 3 "structure/others/trie.hpp"
using namespace std;
struct TrieNode {
vector<int> nxt;
TrieNode() {}
TrieNode(int char_size) {
nxt.resize(char_size, -1);
}
};
template <typename Node = TrieNode>
struct Trie {
public:
vector<Node> nodes;
int root;
int char_size;
int margin;
bool init = false;
int node_cnt;
Trie(int char_size, int margin, int node_size = -1) : char_size(char_size), margin(margin) {
if (node_size != -1) {
init = true;
nodes.resize(node_size);
node_cnt = 0;
}
root = new_node();
}
int new_node() {
if (init) {
nodes[node_cnt] = Node(char_size);
return node_cnt++;
} else {
nodes.push_back(Node(char_size));
return nodes.size() - 1;
}
}
void add(const string &s) {
int n = s.size();
int now = root;
for (int i = 0; i < n; i++) {
const int c = s[i] - margin;
if (nodes[now].nxt[c] == -1) {
nodes[now].nxt[c] = new_node();
}
now = nodes[now].nxt[c];
}
}
};
#line 7 "structure/others/binary-trie.hpp"
using namespace std;
struct Node : public TrieNode {
int cnt;
Node(int char_size) : TrieNode(char_size) {
cnt = 0;
}
};
struct BinaryTrie : public Trie<Node> {
BinaryTrie() : Trie(2, '0') {}
explicit BinaryTrie(int node_size) : Trie(2, '0', node_size) {}
void add_number(uint64_t x, int max_bit = 63) {
int now = root;
for (int i = max_bit; i >= 0; i--) {
int b = (x >> i) & 1;
if (nodes[now].nxt[b] == -1) {
nodes[now].nxt[b] = new_node();
}
now = nodes[now].nxt[b];
nodes[now].cnt++;
}
}
void erase_number(uint64_t x, int max_bit = 63) {
int now = root;
for (int i = max_bit; i >= 0; i--) {
int b = (x >> i) & 1;
now = nodes[now].nxt[b];
nodes[now].cnt--;
}
}
uint64_t max_xor(uint64_t x, int max_bit = 63) {
int now = root;
uint64_t ans = 0;
for (int i = max_bit; i >= 0; i--) {
int b = (x >> i) & 1;
int want = b ^ 1;
if (nodes[now].nxt[want] != -1 && nodes[nodes[now].nxt[want]].cnt > 0) {
ans |= (1ULL << i);
now = nodes[now].nxt[want];
} else if (nodes[now].nxt[b] != -1 && nodes[nodes[now].nxt[b]].cnt > 0) {
now = nodes[now].nxt[b];
} else {
break;
}
}
return ans;
}
};