hduoj6625.three arrays

Title description

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

General idea

Given arrays a and b, rearrange ab and set c i = a i xor b i to
find the smallest lexicographical c

BB

On the 7th, the fairy came back in the last half an hour.
Some very magical methods may be a correct solution.

answer

One property: if a, b, c, d are not equal to each other, and a xor b=c xor d, then the first selection of ab is the same as the first selection of cd,
so each time you choose a pair of XOR and the smallest number

Obviously, it is conceivable to build two tries and try to run in the same direction each time.
There is a problem: if the current two points have two sons each, then there will be disagreements, the worst time is O(n)

Because the deleted point will affect only log points, so obviously (?) It is conceivable that the memory of (?)
Hey do not have two points
in accordance with greedy strategy, only the current two points each have two sons when There will be divergence, otherwise it will only go to one point.
If there is a divergence, record the current direction (0/1), otherwise just record a number, so that each movement can be given an independent label, which can be used in backtracking Hash records the minimum value that can be formed in the subtree.
Just draw it and you can find that when the tree has not been changed , for a node in a tree, it will definitely correspond to another unique node, so just record the path.


This is still too naive . After seeing a lot of battles , we can find that each path of too young too simple corresponds to a unique pair of points,
so the answer of the subtree is recorded on the node of the first tree. Indicates the minimum value that can be constructed from (the node, the corresponding point of the node in the second tree) down, and by the way, record the point pair that obtains the minimum value

When deleting, delete from the found point upwards, and clear all its ancestors. This time is log
(in fact, all point pairs containing one of these two points should be deleted , but because the nodes of the two trees are both One-to-one correspondence, so you can do it together) The
first time of violence is O(n log ai), after each time it is O(log ai), and the total is still O(n log ai)

Correctness can be understood perceptually by drawing several situations

code

Welcome to 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;
		}
	}
}

Guess you like

Origin blog.csdn.net/gmh77/article/details/98506701