Perfect Security (01 dictionary tree)

Topic link

Meaning of the question: Give you two sequences A and B, find a sequence C c[i]=a[i]^b[i] You can rearrange the B sequence, and the answer should be the smallest lexicographical order.

Idea: Build a tree for the B sequence, and then search in the A sequence. In order to find the number as small as possible, then when you are greedy, you need to look at the point on the 01 tree and whether there is the same as the current position. The answer has no effect. If not, you can only add the current bit XOR value (1<<i), and delete the node of the dictionary tree. We use sum[i] to record. If the current node has several child nodes to go, When the child node is reduced to 0, it cannot go.

//#pragma GCC optimize(2)
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
#define SIS std::ios::sync_with_stdio(false)
#define space putchar(' ')
#define enter putchar('\n')
#define lson root<<1
#define rson root<<1|1
typedef pair<int,int> PII;
const int mod=1e9+7;
const int N=1e7+5;

int gcd(int a,int b)
{
    
    
    return b==0?a:gcd(b,a%b);
}
 
ll lcm(ll a,ll b)
{
    
    
    return a*(b/gcd(a,b));
}
 
template <class T>
void read(T &x)
{
    
    
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-')
            op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op)
        x = -x;
}
template <class T>
void write(T x)
{
    
    
    if(x < 0)
        x = -x, putchar('-');
    if(x >= 10)
         write(x / 10);
    putchar('0' + x % 10);
}
ll qsm(int a,int b,int p)
{
    
    
    ll res=1%p;
    while(b)
    {
    
    
        if(b&1)
            res=res*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return res;
}
int trie[N][2],root, tot;
int sum[N];
int a[N];

void Insert(int  x)
{
    
    
    
    root = 0;
    for (int i = 30; i >=0; i--)
    {
    
    
        int id =x>>i&1;//转为2进制;
        if (!trie[root][id]){
    
       
            trie[root][id] = ++tot;
        }
        root = trie[root][id];
        sum[root]++;
    }
    //sum[root]=x;
}
int Search(int x)
{
    
    
    root = 0;
    int res=0;
    for (int i = 30; i>=0; i--)
    {
    
    
        int id =x>>i&1;
        if(trie[root][id]&&sum[trie[root][id]])
        {
    
    
            root=trie[root][id];
        }
        else{
    
    
            root=trie[root][id^1];
            res|=1<<i;

        }
        sum[root]--;
            
    }
    return res;
}

int main()
{
    
    

  



      int n,m;
      scanf("%d",&n);
      for(int i=1;i<=n;i++)scanf("%d",&a[i]);
      for(int i=1;i<=n;i++){
    
    
          int x;
          scanf("%d",&x);
          Insert(x);
      }
      
      int tm=0;
      for(int i=1;i<=n;i++)
      {
    
    
          printf("%d ",Search(a[i]));

      }
     
      
       
      

    return 0;

}


Guess you like

Origin blog.csdn.net/qq_43619680/article/details/109522591