1. 程式人生 > >nefu1248智力異或 字典樹

nefu1248智力異或 字典樹


CJJ

異或是對應的每位相同為0,不同為1.

根據題意,我們會想到肯定要讓x和每位都與他儘量不同的抑或比較好。

所以可以建立一顆字典樹,先把整個陣列都插入字典樹。字典樹的每個分叉就表示0,1的分界。

從高位到低位。這樣我們就可以一層一層,一位一位的比較,每次走不同的那邊就好了。
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+5;
struct node
{
    int son[2];
}tree[40*maxn];
int root,tot;
int newnode()
{
    tot++;
    tree[tot].son[0]=tree[tot].son[1]=-1;
    return tot;
}
void insert(int x)
{
    int now=root;
    for(int i=30;i>=0;i--)
    {
        int tmp=!!(x&(1<<i));                //控制在01之間
        if(tree[now].son[tmp]==-1)tree[now].son[tmp]=newnode();
        now=tree[now].son[tmp];
    }
}
int query(int x)
{
    int ans=0;
    int now=root;
    for(int i=30;i>=0;i--)
    {
        int tmp=!(x&(1<<i));
        if(tree[now].son[tmp]==-1)now=tree[now].son[tmp^1];
        else
        {
             ans+=(1<<i);
             now=tree[now].son[tmp];
        }
    }
    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
       tot=-1;
       root=newnode();
       int n,q;
       scanf("%d%d",&n,&q);
       for(int i=1;i<=n;i++)
       {
           int x;
           scanf("%d",&x);
           insert(x);
       }
       int y=0;
       while(q--)
       {
           int op;
           scanf("%d",&op);
           if(op==1)
           {
               int x;
               scanf("%d",&x);
               y^=x;

           }
           else
           {
               int x;
               scanf("%d",&x);
               printf("%d\n",query(x^y));
           }
       }
    }
    return 0;
}
<br /><span id="_xhe_temp" width="0" height="0"><br /></span>