link
01字典树,dp, 2100
想了很久才想明白。。总之问题等价于保留尽可能多的数,使只存在一对
(
i
,
j
)
(i, j)
(i,j) 对彼此而言异或值都是最小的。
建立字典树,设
f
p
f_p
fp 表示以
p
p
p 为根的子树最多保留多少个数。对于以
p
p
p 为根的子树,
1.若它没有子节点(即为叶节点),则f[p]=1;
2.若仅有一个子节点,则f[p]=f[p的子节点];
3.若它有两个子节点,则f[p]=max(f[p的子节点]) + 1;
对于3,如果我们考虑取左子树,则无论任取右子树中的哪一个,左子树的连接方式都不会发生变化,即不会产生新的
(
i
,
j
)
(i, j)
(i,j)。而若去另一集合中的2个数,则这两个数一定会产生一对
(
i
,
j
)
(i, j)
(i,j),不满足仅有1对的要求。
代码
// Problem: E. Xor Tree
// Contest: Codeforces - Codeforces Round #683 (Div. 2, by Meet IT)
// URL: https://codeforces.com/contest/1447/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define ll long long
#define ull unsigned long long
#define LL long long
#define db double
#define ld long double
#define endl '\n'
//#define int long long
const int maxn = 2e5 + 10;
const int maxm = 2e5 + 10;
const int N = 1e3 + 10;
const int P = 998244353; //998244353
const int INF = 0x3f3f3f3f;
const double EPS=1e-6;
int nxt[maxn*32][2];
int cnt = 1;
void insert(int x) {
int cur = 1;
for(int i = 31; i >= 0; i--) {
if(!nxt[cur][(x>>i)&1]) nxt[cur][(x>>i)&1] = ++cnt;
cur = nxt[cur][(x>>i)&1];
}
}
int find(int p) {
if(!nxt[p][0] && !nxt[p][1]) return 1;
if(!nxt[p][0]) return find(nxt[p][1]);
if(!nxt[p][1]) return find(nxt[p][0]);
return max(find(nxt[p][1]), find(nxt[p][0])) + 1;
}
void solve() {
int n;
cin >> n;
for(int i = 1; i <= n; i++) {
int x;
cin >> x;
insert(x);
}
cout << n - find(1) << endl;
}