link
dfs,mst,01trie,2300
题解写的很清楚,也是看了题解才会做。。
const int maxn = 2e5 + 10;
int n;
int a[maxn];
int nxt[maxn*30][2], cnt = 1;
void insert(int x) {
int cur = 1;
for(int i = 30; i >= 0; i--) {
if(!nxt[cur][(x>>i)&1]) nxt[cur][(x>>i)&1] = ++cnt;
cur = nxt[cur][(x>>i)&1];
}
}
ll find(int r1, int r2, int dep) {
if(dep < 0) return 0;
ll a1 = -1, a2 = -1;
if(nxt[r1][0] && nxt[r2][0]) a1 = find(nxt[r1][0], nxt[r2][0], dep - 1);
if(nxt[r1][1] && nxt[r2][1]) a2 = find(nxt[r1][1], nxt[r2][1], dep - 1);
if(~a1 && ~a2) return min(a1, a2);//同取左儿子或右儿子
if(~a1) return a1;
if(~a2) return a2;
if(nxt[r1][1] && nxt[r2][0]) a1 = find(nxt[r1][1], nxt[r2][0], dep - 1) + (1ll<<dep);
if(nxt[r1][0] && nxt[r2][1]) a2 = find(nxt[r1][0], nxt[r2][1], dep - 1) + (1ll<<dep);
if(~a1 && ~a2) return min(a1, a2);//只能一边取0一边取1,同时加上1<<dep
if(~a1) return a1;
if(~a2) return a2;
return 0;
}
ll ans;
void dfs(int p, int dep) {
if(dep < 0) return;
if(nxt[p][0] && nxt[p][1]) //不要忘记1ll<<dep,因为在dep深度上已经分叉(不同)了。
ans += find(nxt[p][0], nxt[p][1], dep - 1) + (1ll<<dep);
if(nxt[p][0]) dfs(nxt[p][0], dep - 1);
if(nxt[p][1]) dfs(nxt[p][1], dep - 1);
}
void solve() {
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
n = unique(a + 1, a + n + 1) - a - 1;
for(int i = 1; i <= n; i++) insert(a[i]);
dfs(1, 30);
cout << ans << endl;
}