双01字典树最小XOR(three arrays)--2019 Multi-University Training Contest 5(hdu杭电多校第5场)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6625
题意:
给你两串数 a串,b串,让你一一配对XOR使得新的 C 串字典序最小。
思路:
首先这边有两个问题:
1. 我要怎么知道这两个数配对是最优的:一开始我也不明白(以为选择会有后效性),其实很简单,对 a 里的一个X,在 b 的01树里跑到的最优解Y也一定就是 b 的这个Y在 a 的01树里跑到的最优解X。
2. 如果现在两颗树里跑到的点的下一个只有一种选择的话,肯定就接着跑,但是如果现在两个点的下两个点都有01,那大家跑0还是跑1呢?其实随便选一个就行了,因为你下一次还是会跑另一个数的,虽然不是每次都找到 C 串里的头一个最小值,但是跑完sort一下就行了(答案都是会在里面的)。
1 #define IOS ios_base::sync_with_stdio(0); cin.tie(0); 2 #include <cstdio>//sprintf islower isupper 3 #include <cstdlib>//malloc exit strcat itoa system("cls") 4 #include <iostream>//pair 5 #include <fstream> 6 #include <bitset> 7 //#include <map> 8 //#include<unordered_map> http://acm.hdu.edu.cn/showproblem.php?pid=6625 9 #include <vector> 10 #include <stack> 11 #include <set> 12 #include <string.h>//strstr substr 13 #include <string> 14 #include <time.h>//srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9; 15 #include <cmath> 16 #include <deque> 17 #include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less 18 #include <vector>//emplace_back 19 //#include <math.h> 20 //#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor 21 #include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare) 22 using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation 23 #define fo(a,b,c) for(register int a=b;a<=c;++a) 24 #define fr(a,b,c) for(register int a=b;a>=c;--a) 25 #define mem(a,b) memset(a,b,sizeof(a)) 26 #define pr printf 27 #define sc scanf 28 #define ls rt<<1 29 #define rs rt<<1|1 30 void swapp(int &a,int &b); 31 double fabss(double a); 32 int maxx(int a,int b); 33 int minn(int a,int b); 34 int Del_bit_1(int n); 35 int lowbit(int n); 36 int abss(int a); 37 //const long long INF=(1LL<<60); 38 const double E=2.718281828; 39 const double PI=acos(-1.0); 40 const int inf=(1<<29); 41 const double ESP=1e-9; 42 const int N=(int)31e5+10; 43 int read(){ 44 int x=0,f=1;char ch=getchar(); 45 for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; 46 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; 47 return x*f; 48 } 49 int n; 50 struct Trie 51 { 52 int tr[N][2],val[N],sz[N][2],rt,tot; 53 void init() 54 { 55 rt=tot=0; 56 for(int i=0;i<=n*31;++i) 57 tr[i][0]=tr[i][1]=val[i]=sz[i][0]=sz[i][1]=0; 58 } 59 void insert(int x) 60 { 61 rt=0; 62 for(int i=30;i>=0;--i) 63 { 64 int id=(x>>i)&1; 65 if(!tr[rt][id]) tr[rt][id]=++tot; 66 ++sz[rt][id]; 67 rt=tr[rt][id]; 68 } 69 val[rt]=x; 70 } 71 }a,b; 72 73 int ans[100005]; 74 int search(int rt1,int rt2) 75 { 76 while(1)//写成递归可能会TLE; 77 { 78 if(a.val[rt1]||b.val[rt2]) 79 return a.val[rt1]^b.val[rt2]; 80 if(a.sz[rt1][1]&&b.sz[rt2][1])// 有同11/00就走 81 { 82 --a.sz[rt1][1];--b.sz[rt2][1]; 83 rt1=a.tr[rt1][1],rt2=b.tr[rt2][1]; 84 continue; 85 } 86 if(a.sz[rt1][0]&&b.sz[rt2][0]) 87 { 88 --a.sz[rt1][0];--b.sz[rt2][0]; 89 rt1=a.tr[rt1][0],rt2=b.tr[rt2][0]; 90 continue; 91 } 92 int to1,to2; 93 to1=a.sz[rt1][0]?0:1;//实在没有相同的能走就走; 94 to2=b.sz[rt2][0]?0:1; 95 --a.sz[rt1][to1],--b.sz[rt2][to2]; 96 rt1=a.tr[rt1][to1],rt2=b.tr[rt2][to2]; 97 } 98 } 99 100 int main() 101 { 102 int T; 103 T=read(); 104 while(T--) 105 { 106 n=read(); 107 a.init();b.init(); 108 for(int i=1;i<=n;++i) 109 { 110 int t; 111 t=read(); 112 a.insert(t); 113 } 114 for(int i=1;i<=n;++i) 115 { 116 int t; 117 t=read(); 118 b.insert(t); 119 } 120 for(int i=1;i<=n;++i) 121 ans[i]=search(0,0); 122 sort(ans+1,ans+1+n); 123 for(int i=1;i<=n;++i) 124 printf("%d%c",ans[i],i==n?'\n':' '); 125 } 126 return 0; 127 } 128 129 /**************************************************************************************/ 130 131 int maxx(int a,int b) 132 { 133 return a>b?a:b; 134 } 135 136 void swapp(int &a,int &b) 137 { 138 a^=b^=a^=b; 139 } 140 141 int lowbit(int n) 142 { 143 return n&(-n); 144 } 145 146 int Del_bit_1(int n) 147 { 148 return n&(n-1); 149 } 150 151 int abss(int a) 152 { 153 return a>0?a:-a; 154 } 155 156 double fabss(double a) 157 { 158 return a>0?a:-a; 159 } 160 161 int minn(int a,int b) 162 { 163 return a<b?a:b; 164 }