题解 [CF1446C] Xor Tree
这都什么神仙题
可以用trie树按题意建图,但并没有什么用
正解考虑一个性质:
我们如何check一个序列是不是good sequence呢?
一个性质是依据最高有效位是0还是1将原序列分为两个集合 \(s_0\) 和 \(s_1\)
于是仅当 \(|s_0|\geqslant 2\) 并且 \(|s_1|\geqslant 2\) 时原序列是good sequence
证明考虑一个点肯定会向(如果有)最高位与自己相同的点连边
于是当上面情况出现时原图会分成至少两个不连通的部分
所以令 \(f(s)\) 为集合 \(s\) 中能形成的最长good sequence长度
有
\[f(s)=\begin{cases}f(s_0)&s_1=\varnothing\\ f(s_1)&s_0=\varnothing\\ max(f(s_0), f(s_1))+1&other\end{cases}
\]
递归做即可
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int a[N];
int solve(int u, int l, int r) {
if (u<0) return r-l+1;
int mid=l;
while (mid<=r && !(a[mid]&(1<<u))) ++mid;
if (mid==l || mid>r) return solve(u-1, l, r);
else return max(solve(u-1, l, mid-1), solve(u-1, mid, r))+1;
}
signed main()
{
n=read();
for (int i=1; i<=n; ++i) a[i]=read();
sort(a+1, a+n+1);
printf("%d\n", n-solve(30, 1, n));
return 0;
}