VK Cup 2018 Round 1: C. Perfect Security(01字典树)

time limit per test  3.5 seconds
memory limit per test  512 megabytes
input  standard input
output  standard output

Alice has a very important message M consisting of some non-negative integers that she wants to keep secret from Eve. Alice knows that the only theoretically secure cipher is one-time pad. Alice generates a random key K of the length equal to the message's length. Alice computes the bitwise xor of each element of the message and the key (, where  denotes the bitwise XOR operation) and stores this encrypted message A. Alice is smart. Be like Alice.

For example, Alice may have wanted to store a message M = (0, 15, 9, 18). She generated a key K = (16, 7, 6, 3). The encrypted message is thus A = (16, 8, 15, 17).

Alice realised that she cannot store the key with the encrypted message. Alice sent her key K to Bob and deleted her own copy. Alice is smart. Really, be like Alice.

Bob realised that the encrypted message is only secure as long as the key is secret. Bob thus randomly permuted the key before storing it. Bob thinks that this way, even if Eve gets both the encrypted message and the key, she will not be able to read the message. Bob is not smart. Don't be like Bob.

In the above example, Bob may have, for instance, selected a permutation (3, 4, 1, 2) and stored the permuted key P = (6, 3, 16, 7).

One year has passed and Alice wants to decrypt her message. Only now Bob has realised that this is impossible. As he has permuted the key randomly, the message is lost forever. Did we mention that Bob isn't smart?

Bob wants to salvage at least some information from the message. Since he is not so smart, he asks for your help. You know the encrypted message A and the permuted key P. What is the lexicographically smallest message that could have resulted in the given encrypted text?

More precisely, for given A and P, find the lexicographically smallest message O, for which there exists a permutation π such that  for every i.

Note that the sequence S is lexicographically smaller than the sequence T, if there is an index i such that Si < Ti and for all j < i the condition Sj = Tj holds.

Input

The first line contains a single integer N (1 ≤ N ≤ 300000), the length of the message.

The second line contains N integers A1, A2, ..., AN (0 ≤ Ai < 230) representing the encrypted message.

The third line contains N integers P1, P2, ..., PN (0 ≤ Pi < 230) representing the permuted encryption key.

Output

Output a single line with N integers, the lexicographically smallest possible message O. Note that all its elements should be non-negative.

Examples
input
Copy
3
8 4 13
17 2 7
output
10 3 28
input
Copy
5
12 7 87 22 11
18 39 9 12 16
output
0 14 69 6 44


题意:给你n个数a[1~n],再给你n个数b[1~n],你可以将b[]随意打乱,然后计算c[i] = a[i]^b[i]

求出字典序最小的c序列


01字典树裸题,将b[]里面所有数加入字典树,之后对于每个a[i],就是在字典树里面找个最合适的b[x]使得a[i]^b[x]最小,之后将b[x]从字典树中删除就行了


#include<stdio.h>
#include<algorithm>
using namespace std;
int a[300005];
typedef struct Trie
{
	int sum;
	Trie *next[2];
}Trie;
void Create(Trie *root, int x)
{
	int now, i;
	Trie *p = root;
	for(i=30;i>=0;i--)
	{
		now = 0;
		if(x&(1<<i))
			now = 1;
		if(p->next[now]==NULL)
		{
			Trie *temp = new Trie;
			temp->next[0] = temp->next[1] = NULL;
			temp->sum = 0;
			p->next[now] = temp;
		}
		p = p->next[now];
		p->sum++;
	}
}
int Query(Trie *root, int x)
{
	int now, i, ans = 0;
	Trie *p = root;
	for(i=30;i>=0;i--)
	{
		now = 0;
		if(x&(1<<i))
			now = 1;
		if(p->next[now]==NULL || p->next[now]->sum==0)
			p = p->next[now^1], ans += (1<<i);
		else
			p = p->next[now];
		p->sum--;
	}
	return ans;
}
int main(void)
{
	int n, i, x;
	Trie *root = new Trie;
	root->next[0] = root->next[1] = NULL;
	root->sum = 0;
	scanf("%d", &n);
	for(i=1;i<=n;i++)
		scanf("%d", &a[i]);
	for(i=1;i<=n;i++)
	{
		scanf("%d", &x);
		Create(root, x);
	}
	for(i=1;i<=n;i++)
		printf("%d ", Query(root, a[i]));
	puts("");
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值