codeforces1446 C. Xor Tree

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

去年暑假多校补了两道稳定婚姻关系,今天把这题做成图论题自闭了两小时

看了牛逼网友十多分钟写完的代码,我真是草了感觉又要回绿重造经典再现了

直接考虑吧所有数字按位插入字典树,然后考虑dfs,如果字典树中某一棵子树中有两个点,那么由于这棵子树向上位都是相同的,那么这棵子树内部的点一定是两两匹配最小的

接下来我们考虑如何贪心得到最多的点

我们考虑如何计算字典树上没有个点的值,如果他左右两棵子树都有点,而且已经计算过了他们最多可以取多少可以使得只有一对互为异或最小,分别为l,r,那么这个点的答案就是max(l,r)+1,也就是要么左子树全选,右子树选一个点,这样右子树的那个点的异或对应最小值就是左子树的某个点了,而且异或值要跨过当前枚举点的这一位,也就是这一位为1

可以在字典树上写,也可以对a数组排序以后直接在数列上分治,分治一段区间在前已经枚举的i位完全相同,再考虑这一位

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=2e5+10;

int n,m,cnt,tot,cas,ans;
int a[maxl],b[maxl],num[maxl*32];
int ind[maxl*32],sz[maxl*32],tr[maxl*32][2];
bool vis[maxl],pr[maxl];
char s[maxl];
vector<int> e[maxl];

inline void prework()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		int u=0,c;
		for(int j=30;j>=0;j--)
		{
			c=(a[i]>>j)&1;
			if(!tr[u][c])	
				tr[u][c]=++tot;
			u=tr[u][c];++num[u];
		}
		ind[u]=i;
	}
}

inline int dfs(int u)
{
	if(!tr[u][0] && !tr[u][1])
		return 1;
	int l=0,r=0;
	if(tr[u][0])
		l=dfs(tr[u][0]);
	if(tr[u][1])
		r=dfs(tr[u][1]);
	if(!tr[u][1])
		return l;
	if(!tr[u][0])
		return r;
	return max(l,r)+1;
}

inline void mainwork()
{
	ans=n-dfs(0);
}

inline void print()
{
	printf("%d\n",ans);
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值