Vitya and Strange Lesson CodeForces - 842D

原题链接

Trie+位运算

错误思路:

        枚举数组里每一个数与询问的数异或,利用桶排序求最小值.时间复杂度O(n^2),TLE

正确思路:

        想AC本题首先要明确几个性质:

  1. x^y^z = x^(y^z)
  2. 0~n位二进制数与n位二进制数异或的结果仍然在0~n位二进制数内,且不存在不同数取相同值的结果
  3. 3e5的二进制数大概在19位,在这19位以内每一个数除了数组内部都可能取到最小值

因此,求不在数组的最小值,就是求不在数组内的数字与询问的值异或的最小值,注意数字>3e5的也可能取到最小值,因为3e5!=1111...(19位)

 1 #include <iostream>
 2 #include <cstring> 
 3 using namespace std;
 4 const int N = 6e5+10;
 5 int vis[N],son[N*2][2],idx;
 6 void insert_t(int x)
 7 {
 8     int p = 0;
 9     for(int i=31;~i;i--){
10         int u = x>>i&1;
11         if(!son[p][u]) son[p][u] = ++idx;
12         p = son[p][u];
13     }
14 }
15 int query(int x)
16 {
17     int p = 0,ans = 0;
18     for(int i=31;~i;i--){
19         int u = x>>i&1;
20         if(!son[p][u]){
21             ans+=(1<<i);
22             p = son[p][!u];
23         }else p = son[p][u];
24     }
25     return ans;
26 }
27 int main()
28 {
29     int n,m,t = 0;
30     scanf("%d%d",&n,&m);
31     for(int i=1;i<=n;i++){
32         int x; scanf("%d",&x);
33         vis[x] = 1;//将进入数组的元素 标记 
34     }
35     for(int i=0;i<=6e5;i++)
36         if(!vis[i]) insert_t(i);
37     for(int i=1;i<=m;i++){
38         int x; scanf("%d",&x);
39         t = t^x;
40         printf("%d\n",query(t));
41     }
42     return 0;
43 }

 

posted @ 2021-01-01 22:31  acmloser  阅读(107)  评论(0编辑  收藏  举报