Codeforces 948D Perfect Security(字典树)
Posted doggod
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 948D Perfect Security(字典树)相关的知识,希望对你有一定的参考价值。
题目链接:Perfect Security
题意:给出N个数代表密码,再给出N个数代表key。现在要将key组排序,使key组和密码组的亦或所形成的组字典序最小。
题解:要使密码组里面每个数都找到能使其亦或和最小的数可以将key建成一棵字典树(这里建树方式很关键,可以每个数都从2^31开始建树,这样可以使我们在遍历树查询更加方便)。之后再遍历密码组每次在字典树里面找到一个能使它亦或和最小的数,再将这个数从字典树中删掉。。。 字典树太久不写,很多东西都忘记了!
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAX_N = 3e5+9; 4 const int INF = 1e9+9; 5 int tran[MAX_N*35][2]; //跳转到下一个节点的数组 6 int sum[MAX_N*35],ans[MAX_N],A[MAX_N],P[MAX_N]; //sum - 记录每个节点记录的数的数量 7 int N,M,T,S,siz; 8 void init(){ 9 for(int i=0;i<MAX_N;i++){ 10 tran[i][0] = tran[i][1] = 0; 11 sum[i] = 0; 12 } 13 siz = 0; 14 } 15 void _insert(int x){ 16 int now = 0; 17 for(int i=31;i>=0;i--){ //从31开始就可以保证从高位开始建树了 18 int t = 0; 19 if(x & (1<<i)) t = 1; 20 if(!tran[now][t]) tran[now][t] = ++siz; // 这里siz指的时节点的编号,这里如果下一个指向的节点没有的话就新生成一个节点给它。 21 sum[tran[now][t]] ++; //节点上记录的数的数量加一 22 now = tran[now][t]; //跳转到下一个节点 23 } 24 } 25 void query(int id , int x){ 26 int now = 0; 27 int res = 0; 28 for(int i=31;i>=0;i--){ 29 int t =0; 30 if(x & (1<<i)) t = 1; 31 if(!sum[tran[now][t]]){ 32 res += (1<<i); 33 t = 1-t; 34 } 35 sum[tran[now][t]] --; 36 now = tran[now][t]; 37 38 } 39 ans[id] = res; 40 } 41 int main() 42 { 43 while(cin>>N) 44 { 45 init(); 46 for(int i=0;i<N;i++){ 47 scanf("%d",&A[i]); 48 } 49 for(int i=0;i<N;i++){ 50 scanf("%d",&P[i]); 51 _insert(P[i]); 52 } 53 for(int i=0;i<N;i++){ 54 query(i,A[i]); 55 cout<<ans[i]<<" "; 56 } 57 cout<<endl; 58 59 } 60 return 0; 61 }
以上是关于Codeforces 948D Perfect Security(字典树)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 388 D. Fox and Perfect Sets
CodeForces947 C. Perfect Security 异或Trie
A - Perfect Team CodeForces - 1221C
Codeforces 986D Perfect Encoding FFT 分治 高精度