https://codeforces.ml/contest/888/problem/G
struct TrieNode {
int cnt;
int num;
int nxt[2];
void Init() {
cnt = 0;
num = 0;
memset(nxt, 0, sizeof(nxt));
}
};
struct Trie {
static const int MAXN = 200000;
TrieNode tn[MAXN * 32 + 5];
int root, top;
int NewNode() {
tn[++top].Init();
return top;
}
void Init() {
top = 0;
root = NewNode();
}
void Insert(int a) {
int cur = root;
++tn[cur].cnt;
for(int i = 30; i >= 0; --i) {
int &nxt = tn[cur].nxt[a >> i & 1];
if(!nxt)
nxt = NewNode();
tn[nxt].num = tn[cur].num | (a & (1 << i));
cur = nxt;
++tn[cur].cnt;
}
}
ll help(int cur, int Rnum) {
if(tn[cur].nxt[0] == 0 && tn[cur].nxt[1] == 0)
return tn[cur].num ^ Rnum;
if(tn[cur].nxt[0] == 0)
return help(tn[cur].nxt[1], Rnum);
if(tn[cur].nxt[1] == 0)
return help(tn[cur].nxt[0], Rnum);
if((tn[tn[cur].nxt[0]].num ^ Rnum) < (tn[tn[cur].nxt[1]].num ^ Rnum))
return help(tn[cur].nxt[0], Rnum);
else
return help(tn[cur].nxt[1], Rnum);
}
ll count(int cur, int Lroot) {
if(tn[cur].nxt[0] == 0 && tn[cur].nxt[1] == 0)
return help(Lroot, tn[cur].num);
if(tn[cur].nxt[0] == 0)
return count(tn[cur].nxt[1], Lroot);
if(tn[cur].nxt[1] == 0)
return count(tn[cur].nxt[0], Lroot);
return min(count(tn[cur].nxt[1], Lroot), count(tn[cur].nxt[0], Lroot));
}
ll calc(int cur) {
if(cur == 0 || tn[cur].cnt <= 1)
return 0;
if(tn[cur].nxt[0] == 0 && tn[cur].nxt[1] == 0)
return 0;
if(tn[cur].nxt[0] == 0)
return calc(tn[cur].nxt[1]);
if(tn[cur].nxt[1] == 0)
return calc(tn[cur].nxt[0]);
ll res = calc(tn[cur].nxt[0]) + calc(tn[cur].nxt[1]);
ll tmp = count(tn[cur].nxt[1], tn[cur].nxt[0]);
return res + tmp;
}
} trie;