codeforces 1446C - Xor Tree (Trie + dfs)

题目链接:https://codeforces.com/problemset/problem/1446/C

还是想不到。。

将所有的数都插入到 \(trie\) 中,根据异或的性质,同一位相同的数,异或起来肯定更小,
所以在 \(trie\) 中,子树内的数字在建好的图中一定在同一个连通块里,

我们设该位在 \(trie\) 中两棵子树的大小分别为 \(S_0, S_1\), 可以发现,如果 \(S < 2\) , 那么肯定这个节点会在另一个集合的连通块中,
如果 \(S > 2\),那就要将 \(S\) 减为 \(1\), 使其可以联通到另一个集合的连通块中,

所以问题就转化成了:在 \(trie\) 中挑出一棵最大的树,答案就是 \(n - 树的size\)

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;

const int maxn = 200010;
 
int n, rt = 0, tot = 0;
int a[maxn];

struct Trie{
	int son[2];
	int sz;
}t[maxn * 32];

void insert(int x){
	int p = rt;
	for(int i = 30; i >= 0 ; --i){
		int c = (x >> i) & 1;
		if(!t[p].son[c]) t[p].son[c] = ++tot;
		p = t[p].son[c];
		t[p].sz += 1;
//		printf("%d ", p);
	} //printf("\n");
	t[p].sz = 1;
}

int ans = 0;
int sz[maxn * 30];
void dfs(int u, int sum){
//	printf("%d %d\n", u, sum);
	if(!t[u].son[0]){
		if(t[u].son[1]) dfs(t[u].son[1], sum);
		else ans = max(ans, sum + 1);
	} else if(!t[u].son[1]){

		if(t[u].son[0]) dfs(t[u].son[0], sum);
		else ans = max(ans, sum + 1);
	} else{
		dfs(t[u].son[0], sum + 1);
		dfs(t[u].son[1], sum + 1);
	}
//	ans = max(ans , sum);
}

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }

int main(){
	n = read();
	for(int i = 1 ; i <= n ; ++i) {
		a[i] = read();
		insert(a[i]);
	}
	
	dfs(rt, 0);
	
	printf("%d\n", n - ans);
	
	return 0;
}
posted @ 2020-12-04 10:31  Tartarus_li  阅读(147)  评论(0编辑  收藏  举报