一、题目
二、解法
这种异或的题很容易想到 t i r e \tt tire tire,我们不妨把他放在 t i r e \tt tire tire 树上思考。
俗话说正难则反,我们要求点的最小删除数是可以转化成点的最大保留数的。
记住,我们要在 t i r e \tt tire tire 树上思考,坚信他的美妙性质能帮助我们解决本题。求解最大保留数可以在 t i r e \tt tire tire 树上 d p dp dp,设 f [ i ] f[i] f[i] 为 i i i 子树内的最大保留数,首先考虑没有左 / / /右子树的情况,直接赋值就行了。
因为我们要把两个子树建立联系,所以一定是在某一边只选了一个点,才能保证连的边连接了这两个子树,所以转移方程: f [ i ] = max ( f [ l s ] , f [ r s ] ) + 1 f[i]=\max(f[ls],f[rs])+1 f[i]=max(f[ls],f[rs])+1
#include <cstdio>
#include <iostream>
using namespace std;
const int M = 30*200005;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,cnt,rt,f[M],a[M],ls[M],rs[M];
void insert(int &x,int v,int d)
{
if(!x) x=++cnt;
if(d==0)
{
f[x]++;
return ;
}
if((v&(1<<d-1))==0)
insert(ls[x],v,d-1);
else
insert(rs[x],v,d-1);
}
void dp(int x,int d)
{
if(!x || d==0) return ;
dp(ls[x],d-1);dp(rs[x],d-1);
if(!ls[x]) f[x]=f[rs[x]];
else if(!rs[x]) f[x]=f[ls[x]];
else f[x]=max(f[ls[x]],f[rs[x]])+1;
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)
insert(rt,read(),31);
dp(rt,31);
printf("%d\n",n-f[rt]);
}