CF923C Perfect Security

原题链接

想在vj上做来着..结果vj半天登不上去...

错误思路:

       暴力枚举TLE

错误思路2:

      用cnt数组标记用了的数字,但注意如果我们只标记叶子结点,那么就会陷入死循环,因为每次都要走到底才能知道是否能用

正确思路:

      用cnt数组标记当前结点的子节点的个数,因为可能存在重复数字,所以不能简单的赋值1,当我们在查询的时候,将要走的子节点个数-1即可.

要注意的是我们要插入树的是第二行的值,因为第一行的数字顺序是固定的

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 #define pii pair<int,int>
 5 const int N = 300010; 
 6 int a[N],son[N*32][2],cnt[N*32],idx;//不能到叶子结点才来看是否用过,不然每次都要重走 
 7 void insert_t(int x)
 8 {
 9     int p = 0;
10     for(int i=31;~i;i--){
11         int t = x>>i&1;
12         if(!son[p][t]) son[p][t] = ++idx;
13         p = son[p][t];
14         cnt[p]++;
15     }
16 }
17 int query(int x)
18 {
19     int p = 0,res = 0;
20     for(int i=31;~i;i--){
21         int t = x>>i&1;
22         if(son[p][t]&&cnt[son[p][t]]){
23             cnt[son[p][t]]--;
24             p = son[p][t];
25         }else if((son[p][t]&&!cnt[son[p][t]])||!son[p][t]){
26             cnt[son[p][!t]]--;
27             res+=(1<<i);
28             p = son[p][!t];
29         }
30     }
31     return res;
32 }
33 int main()
34 {
35     int n;
36     scanf("%d",&n);
37     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
38     for(int i=1;i<=n;i++){
39         int y; scanf("%d",&y);
40         insert_t(y);
41     }
42     for(int i=1;i<=n;i++){
43         if(i!=1) printf(" ");
44         printf("%d",query(a[i]));
45     }
46     printf("\n");
47     return 0;
48 } 

 

posted @ 2021-01-02 11:03  acmloser  阅读(106)  评论(0编辑  收藏  举报