自己在cf上提交一直wa3,但是这个测试数据较长,后面都是省略号看不到,并且也不方便手玩
后来自己也试了一些能手玩的小数据,自己的输出都和通过代码一样
以下是自己的实现,写的是trie树更新查询的方法
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, L = 30, NL2 = N * (L + 1) * 2;
struct trie
{
int ch[2];
int sz, id;
trie(int _sz = 0)
{
ch[0] = ch[1] = -1;
sz = _sz;
id = 0;
}
}tree[NL2];
struct connect
{
int u, v, dist;
connect(){};
connect(int _u, int _v, int _dist)
{
u = _u;
v = _v;
dist = _dist;
}
}con[N];
bool cmp(const connect &aa, const connect &bb)
{
return aa.dist < bb.dist ||
(aa.dist == bb.dist && aa.u < bb.u) ||
(aa.dist == bb.dist && aa.u == bb.u && aa.v < bb.v);
}
int a[N], fa[N], mindist[N];
int n, len = -1;
long long ans = 0;
int findf(int x)
{
if(fa[x] == x)
return x;
fa[x] = findf(fa[x]);
return fa[x];
}
void build(int root, int x)
{
int id = root;
for(int i = L - 1; i >= 0; --i)
{
int cur = (x >> i) & 1;
tree[id].ch[cur] = ++len;
tree[len] = trie(1);
id = len;
}
tree[id].id = root;
}
void update(int des, int sou, int delta)
{
tree[des].sz += tree[sou].sz * delta;
if(tree[sou].id)
{
tree[des].id = tree[sou].id;
return;
}
for(int i = 0; i <= 1; ++i)
{
if(tree[sou].ch[i] != -1)
{
if(tree[des].ch[i] == -1)
{
tree[des].ch[i] = ++len;
tree[len] = trie();
}
update(tree[des].ch[i], tree[sou].ch[i], delta);
}
}
}
void findmin(int root, int x, int sou_id)
{
int id = root, xorans = 0;
for(int i = L - 1; i >= 0; --i)
{
int cur = (x >> i) & 1;
if(tree[id].ch[cur] != -1 && tree[tree[id].ch[cur]].sz >= 1)
id = tree[id].ch[cur];
else
{
id = tree[id].ch[cur ^ 1];
xorans |= (1 << i);
}
}
con[sou_id] = connect(tree[id].id, sou_id, xorans);
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
n = unique(a + 1, a + 1 + n) - (a + 1);
tree[++len] = trie();
for(int i = 1; i <= n; ++i)
{
tree[++len] = trie(1);
fa[i] = i;
}
for(int i = 1; i <= n; ++i)
build(i, a[i]);
for(int i = 1; i <= n; ++i)
update(0, i, 1);
int blocks = n;
while(blocks > 1)
{
for(int i = 1; i <= n; ++i)
{
update(0, findf(i), -1);
findmin(0, a[i], i);
update(0, findf(i), 1);
}
sort(con + 1, con + 1 + n, cmp);
for(int i = 1; i <= n; ++i)
{
int u = con[i].u, v = con[i].v;
int x = findf(u), y = findf(v);
if(x != y)
{
ans += con[i].dist;
--blocks;
if(tree[x].sz >= tree[y].sz)
{
fa[y] = x;
update(x, y, 1);
}
else
{
fa[x] = y;
update(y, x, 1);
}
if(blocks == 1)
break;
}
}
}
printf("%lld\n", ans);
}