cf1446C. Xor Tree

发布时间 2023-11-07 18:34:34作者: gan_coder

https://codeforces.com/problemset/problem/1446/C

断断续续想了挺久的,还发现看错题了。

首先一个显然的结论是不会成环,证明显然。

突破口在于从高位往低位考虑,我们按照最高一位的值分成两类,一类是这一位为0,另一类为1,那么显然在我们不进行任何操作的时候,如果两个集合都不为空,那么此时一定不合法,而且我们一定要将其中一个集合的大小调整为1,并且剩下的那个数一定会连到另一个集合的某些数, 并且另一个集合中不存在数会向它连边。

那么直接递归求解即可。
时间复杂度最坏情况 应该是每次对半分,O(nlogn)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<unordered_map>
#include<queue>
#include<bitset>
#define A puts("YES")
#define B puts("NO")
#define fo(i,a,b) for (ll (i)=(a);(i)<=(b);(i)++)
#define fd(i,b,a) for (int (i)=(b);(i)>=(a);(i)--)
#define mk(x,y) make_pair((x),(y))
#define eb(x) .emplace_back(x)
#define lc (o<<1)
#define rc (o<<1|1)
using namespace std;
//typedef __int128 i128;
typedef double db;
typedef long long ll;
//const ll mo=1e9+7;
//const int inf=1<<30;
const int N=2e5+5;
int a[N],n,b[50],x;
int nex[N*2],to[N*2],head[N],tot;
int ch[N][35],cnt,c,now,sz[N];
void cmax(int &x,int y){
	x=max(x,y);
}
int solve(int l,int r,int k){
	if (l>r) return 0;
	if (l==r) return 1;
	
	int s0=0,s1=0,ans=0;
	fo(i,l,r) {
		if (!(a[i]&b[k])) s0++;
		else s1++;
	}
	cmax(ans, solve(l,l+s0-1,k-1)+min(1,s1));
	cmax(ans, solve(l+s0,r,k-1)+min(1,s0));
	
	return ans;
}
int main()
{
//	freopen("data.in","r",stdin);
//	freopen("data.out","w",stdout);

	b[0]=1;
	fo(i,1,30) b[i]=b[i-1]*2;
	
	scanf("%d",&n);
	fo(i,1,n) scanf("%d",&a[i]);
	
	sort(a+1,a+n+1);
	
	printf("%d",n-solve(1,n,30)); 
	


	return 0;
}