题目链接:https://codeforces.com/problemset/problem/1446/C
还是想不到。。
将所有的数都插入到 (trie) 中,根据异或的性质,同一位相同的数,异或起来肯定更小,
所以在 (trie) 中,子树内的数字在建好的图中一定在同一个连通块里,
我们设该位在 (trie) 中两棵子树的大小分别为 (S_0, S_1), 可以发现,如果 (S < 2) , 那么肯定这个节点会在另一个集合的连通块中,
如果 (S > 2),那就要将 (S) 减为 (1), 使其可以联通到另一个集合的连通块中,
所以问题就转化成了:在 (trie) 中挑出一棵最大的树,答案就是 (n - 树的size)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const int maxn = 200010;
int n, rt = 0, tot = 0;
int a[maxn];
struct Trie{
int son[2];
int sz;
}t[maxn * 32];
void insert(int x){
int p = rt;
for(int i = 30; i >= 0 ; --i){
int c = (x >> i) & 1;
if(!t[p].son[c]) t[p].son[c] = ++tot;
p = t[p].son[c];
t[p].sz += 1;
// printf("%d ", p);
} //printf("
");
t[p].sz = 1;
}
int ans = 0;
int sz[maxn * 30];
void dfs(int u, int sum){
// printf("%d %d
", u, sum);
if(!t[u].son[0]){
if(t[u].son[1]) dfs(t[u].son[1], sum);
else ans = max(ans, sum + 1);
} else if(!t[u].son[1]){
if(t[u].son[0]) dfs(t[u].son[0], sum);
else ans = max(ans, sum + 1);
} else{
dfs(t[u].son[0], sum + 1);
dfs(t[u].son[1], sum + 1);
}
// ans = max(ans , sum);
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
n = read();
for(int i = 1 ; i <= n ; ++i) {
a[i] = read();
insert(a[i]);
}
dfs(rt, 0);
printf("%d
", n - ans);
return 0;
}