7310. 【2021.10.18NOIP提高组模拟】doubt

Description

(nle 2 imes 10^5,a_i,b_ile 2^{30})

Solution

看到异或会很自然的想起 ( ext{trie}),考虑对 (a)(b) 分别建一棵 ( ext{trie}),然后同时 ( ext{dfs}) 往下搜索,因为要让 (c) 最小,因此先走同 0 或 同 1,然后对于没匹配完的部分再走不同。

最后对于求出的 (c) 进行排序就可以保证字典序最小。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 200005
using namespace std;
int n,num,a[N],b[N],c[N];
struct node
{
	int tot,tree[N*30][2],size[N*30];
	bool bj[N*30];
	void ins(int x)
	{
		int now=0;
		size[0]++;
		for (int i=30;i>=0;--i)
		{
			int u=x>>i&1;
			if (!tree[now][u]) tree[now][u]=++tot;
			now=tree[now][u];
			size[now]++;
		}
		bj[now]=true;
	}
}trie1,trie2;
int dfs(int x,int y,int sum,int pos)
{
	if (!trie1.size[x]||!trie2.size[y]) return 0;
	if (pos<0)
	{
		int s=min(trie1.size[x],trie2.size[y]);
		for (int i=1;i<=s;++i)
			c[++num]=sum;
		trie1.size[x]-=s;trie2.size[y]-=s;
		return s;
	}
	int res=0;
	if (trie1.tree[x][0]&&trie2.tree[y][0]) res+=dfs(trie1.tree[x][0],trie2.tree[y][0],sum,pos-1);
	if (trie1.tree[x][1]&&trie2.tree[y][1]) res+=dfs(trie1.tree[x][1],trie2.tree[y][1],sum,pos-1);
	if (trie1.tree[x][0]&&trie2.tree[y][1]) res+=dfs(trie1.tree[x][0],trie2.tree[y][1],sum+(1<<pos),pos-1);
	if (trie1.tree[x][1]&&trie2.tree[y][0]) res+=dfs(trie1.tree[x][1],trie2.tree[y][0],sum+(1<<pos),pos-1);
	trie1.size[x]-=res;trie2.size[y]-=res;
	return res;
}
int main()
{
	freopen("doubt.in","r",stdin);
	freopen("doubt.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	for (int i=1;i<=n;++i)
		scanf("%d",&b[i]);
	for (int i=1;i<=n;++i)
		trie1.ins(a[i]);
	for (int i=1;i<=n;++i)
		trie2.ins(b[i]);
	dfs(0,0,0,30);
	sort(c+1,c+num+1);
	for (int i=1;i<=num;++i)
		printf("%d ",c[i]);
	return 0;
}

原文地址:https://www.cnblogs.com/Livingston/p/15427976.html