hduoj6625.three arrays

题目描述

Problem Description
There are three integer arrays a,b,c. The lengths of them are all N. You are given the full contents of a and b. And the elements in c is produced by following equation: c[i]=a[i] XOR b[i] where XOR is the bitwise exclusive or operation.

Now you can rearrange the order of elements in arrays a and b independently before generating the array c. We ask you to produce the lexicographically smallest possible array c after reordering a and b. Please output the resulting array c.

Input
The first line contains an integer T indicating there are T tests.

Each test consists of three lines. The first line contains one positive integer N denoting the length of arrays a,b,c. The second line describes the array a. The third line describes the array b.

  • T≤1000

  • 1≤N≤105

  • integers in arrays a and b are in the range of [0,230).

  • at most 6 tests with N>100

Output
For each test, output a line containing N integers, representing the lexicographically smallest resulting array c.

Sample Input
1
3
3 2 1
4 5 6

Sample Output
4 4 7

Source
2019 Multi-University Training Contest 5

题目大意

给出数组a、b,把ab重排,设ci=ai xor bi
求字典序最小的c

BB

开场-7日神仙最后半小时翻盘
一些很魔幻的做法也许是正解

题解

一个性质:如果a、b、c、d互不相等,且a xor b=c xor d,那么先选ab和先选cd是一样的
所以每次选出一对异或和最小的数即可

很显然可以想到建两棵trie,每次尽量向相同方向跑
这样有个问题:如果当前的两个点都有各两个儿子,那么就会产生分歧,最坏时间为O(n)

因为删点只会影响到log个点,所以很显然(?)可以想到记忆化(?)
欸不是有两个点吗
按照贪心的策略,只有当前的两个点都有各两个儿子时才会产生分歧,否则只会走到一个点上去
若产生分歧则记录当前的方向(0/1),否则随便记一个数,这样就可以给每种走法一个独立的标号,可以在回溯时用hash记录子树中能构成的最小值
随便画一下可以发现,在树还未被改变时,对于一棵树中的一个节点,一定会对应另一个唯一的节点,所以记录路径即可


这样做还是太naive了,我们在身经百战见得多了之后可以发现,too young too simple每一条路径都对应唯一一对点
所以把子树的答案记录在第一棵树的节点上,表示从(该节点,该节点在第二棵树的对应点)往下走能构出的最小值,顺便记录下得出最小值的点对

删除时就从找到的点往上删,把它的祖先全部清空,这样的时间是log的
(其实应该删掉所有包含这两个点之一的点对,但由于两棵树的节点都是一一对应的,所以可以一起做)
第一次暴力的时间是O(n log ai),之后每次是O(log ai),加起来还是O(n log ai)

正确性可以画一下几种情况来感性理解

code

欢迎Hack

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
using namespace std;

int p[32];
int a[100001];
int b[100001];
int A[100001];
int tr[2][3000002][3];
int f[3000002];
int g[3000002][2];
int fa[2][3000002];
int T,n,i,j,k,l;
int len[2];

void clear(int type,int t)
{
    
    
	tr[type][t][0]=0;
	tr[type][t][1]=0;
	tr[type][t][2]=0;
	fa[type][0]=0;
}

void New(int type,int t,int x)
{
    
    
	if (!tr[type][t][x])
	{
    
    
		tr[type][t][x]=++len[type];
		fa[type][len[type]]=t;
	}
}

int dfs(int T,int t1,int t2)
{
    
    
	int s;
	
	if (T==31)
	{
    
    
		f[t1]=0;
		g[t1][0]=t1;
		g[t1][1]=t2;
	}
	
	if (f[t1]>=0)
	return f[t1];
	
	if (tr[0][t1][0] && tr[0][t1][1] && tr[1][t2][0] && tr[1][t2][1])
	{
    
    
		f[t1]=dfs(T+1,tr[0][t1][0],tr[1][t2][0]);
		
		g[t1][0]=g[tr[0][t1][0]][0];
		g[t1][1]=g[tr[0][t1][0]][1];
		
		s=dfs(T+1,tr[0][t1][1],tr[1][t2][1]);
		if (f[t1]>s)
		{
    
    
			f[t1]=s;
			
			g[t1][0]=g[tr[0][t1][1]][0];
			g[t1][1]=g[tr[0][t1][1]][1];
		}
	}
	else
	if (tr[0][t1][0] && tr[1][t2][0])
	{
    
    
		f[t1]=dfs(T+1,tr[0][t1][0],tr[1][t2][0]);
		
		g[t1][0]=g[tr[0][t1][0]][0];
		g[t1][1]=g[tr[0][t1][0]][1];
	}
	else
	if (tr[0][t1][1] && tr[1][t2][1])
	{
    
    
		f[t1]=dfs(T+1,tr[0][t1][1],tr[1][t2][1]);
		
		g[t1][0]=g[tr[0][t1][1]][0];
		g[t1][1]=g[tr[0][t1][1]][1];
	}
	else
	if (tr[0][t1][0] && tr[1][t2][1])
	{
    
    
		f[t1]=dfs(T+1,tr[0][t1][0],tr[1][t2][1]);
		f[t1]|=p[T];
		
		g[t1][0]=g[tr[0][t1][0]][0];
		g[t1][1]=g[tr[0][t1][0]][1];
	}
	else
	if (tr[0][t1][1] && tr[1][t2][0])
	{
    
    
		f[t1]=dfs(T+1,tr[0][t1][1],tr[1][t2][0]);
		f[t1]|=p[T];
		
		g[t1][0]=g[tr[0][t1][1]][0];
		g[t1][1]=g[tr[0][t1][1]][1];
	}
	
	return f[t1];
}

void del(int type,int t)
{
    
    
	int A[233],i,j;
	
	j=0;
	
	--tr[type][t][2];
	while (t>1)
	{
    
    
		++j;
		
		if (tr[type][fa[type][t]][0]==t)
		A[j]=0;
		else
		A[j]=1;
		
		t=fa[type][t];
		
		if (!tr[type][tr[type][t][0]][2])
		tr[type][t][0]=0;
		if (!tr[type][tr[type][t][1]][2])
		tr[type][t][1]=0;
		
		if (t)
		--tr[type][t][2];
	}
	
//	fd(i,30,1)
//	cout<<A[i];
//	cout<<endl;
}

void Del(int t)
{
    
    
	while (t)
	{
    
    
		f[t]=-1;
		g[t][0]=0;
		g[t][1]=0;
		
		t=fa[0][t];
	}
}

int main()
{
    
    
//	freopen("02.in","r",stdin);
//	freopen("a.out","w",stdout);
	
	p[30]=1;
	fd(i,29,1)
	p[i]=p[i+1]*2;
	
	memset(f,255,sizeof(f));
	
	scanf("%d",&T);
	for (;T;--T)
	{
    
    
		scanf("%d",&n);
		fo(i,1,n)
		scanf("%d",&a[i]);
		fo(i,1,n)
		scanf("%d",&b[i]);
		
		clear(0,1);
		clear(1,1);
		len[0]=1;
		len[1]=1;
		
		fo(i,1,n)
		{
    
    
			j=a[i];
			fd(k,30,1)
			{
    
    
				A[k]=j&1;
				j>>=1;
			}
			
			l=1;
			fo(k,1,30)
			{
    
    
				New(0,l,A[k]);
				
				l=tr[0][l][A[k]];
				++tr[0][l][2];
			}
		}
		
		fo(i,1,n)
		{
    
    
			j=b[i];
			fd(k,30,1)
			{
    
    
				A[k]=j&1;
				j>>=1;
			}
			
			l=1;
			fo(k,1,30)
			{
    
    
				New(1,l,A[k]);
				
				l=tr[1][l][A[k]];
				++tr[1][l][2];
			}
		}
		
		fo(i,1,n)
		{
    
    
			dfs(1,1,1);
			if (i<n)
			printf("%d ",f[1]);
			else
			printf("%d",f[1]);
			
			j=g[1][0];
			k=g[1][1];
			
			del(0,j);
			del(1,k);
			
			Del(j);
		}
		printf("\n");
		
		fo(i,1,len[0])
		{
    
    
			f[i]=-1;
			g[i][0]=0;
			g[i][1]=0;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/gmh77/article/details/98506701
今日推荐