📜  给定集合的XOR查询

📅  最后修改于: 2021-04-17 13:45:03             🧑  作者: Mango

给定具有初始元素0的集合S,即S = {0}。任务是在给出Q个查询后执行每个查询,并在类型3的每个查询后打印答案。
我们可以执行三种类型的查询操作:

  • 1 X:我们可以将X添加到集合S中。
  • 2 Y:对于每个元素i,执行i⊕Y。
  • 3:找到集合中的最小元素。

例子:

先决条件:特里。

方法:

我们将尝试使用最小XOR值对问题的trie方法来解决此问题。

  • 因此,在这个问题中,我们有一个二进制trie和一个整数x,我们必须找到XOR(x,y)的最小值,其中y是trie中的某个整数。
  • 现在,要解决此问题,我们将从最高有效位到最低位进行尝试。
  • 假设我们处于第i位:
    如果x [i]为1,我们将沿着具有1的trie的路径前进。
    如果x [i]为0,我们将沿着具有0的路径前进。
    如果在位置i处,我们没有分支要沿着x [i]下降,那么我们将走另一条路。

现在,解决我们的问题。

  • 假设我们在集合中插入了a1,a2,a3,然后对所有与x1,x2,x3进行异或运算,那么它与X = XOR(x1,x2,x3)的异或运算相同。
  • 因此,找到最小值元素等于在与X进行异或后找到(a1,a2,a3)中的最小值。
    我们已经注意到一开始该如何做。
  • 现在,如何回答每个查询。
    令x = XOR(x1,x2,…..,xn),其中x1,x2,…,xn是与集合S的元素进行XOR运算的所有数字。
    1. 对于查询2 ,与xi进行XOR。
      我们不会将trie中的每个元素与xi进行XOR。相反,我们将只更新x = XOR(x,xi)
    2. 对于查询3 ,获取最小元素。
      到目前为止,我们应该已经使用X对整个数组进行了XOR运算。
      因此,现在我们将使用上述方法,通过对集合中所有元素与X进行XOR运算来计算最小值。
    3. 对于查询1 ,插入ai。
      我们不会将ai插入到trie中,而是将XOR(ai,x)插入。原因:
      • 假设我们插入a1,a2,然后与x1进行异或,然后插入a3,然后与x2进行异或。
      • 当我们现在查询最小值时,我们将在以下位置找到最小值:{XOR(a1,x1,x2),XOR(a2,x1,x2),XOR(a3,x1,x2)}
        但是a3只能与x2进行异或运算,而不能与x1进行异或。
      • 因此,至关重要的是,在每时每刻将元素ai插入到trie中时,我们都要插入XOR(ai,x)。这样可以确保当我们计算最小值时,它将抵消先前的XOR。
        因此,在我们的示例中,我们的特里将包含
        {a1,a2,XOR(a3,x1)}。
      • 当查询XOR(x)的最小值时,将使用上述方法{XOR(a1,x1,x2),XOR(a2,x1,x2),XOR(a3,x2)}找到最小值,这就是我们想要的。插入XOR(ai,x)将确保无论我们执行的是哪种最小操作,我们都不会在任何ai上进行任何不必要的XOR。

以下是此方法的C++实现:

// C++ program to operate 
// queries in a given set
#include 
using namespace std;
  
const int Maxbits = 30;
  
// Function for Query 1
void Insert(int x, int curx, 
            int* sz, int trie[100][2])
{
    // XOR each element before
    // storing it in the trie.
    x = x ^ curx;
    int p = 0;
  
    // Storing xored element in the trie.
    for (int i = Maxbits - 1; i >= 0; i--)
    {
        if (!trie[p][x >> i & 1])
            trie[p][x >> i & 1] = (*sz)++;
  
        p = trie[p][x >> i & 1];
    }
}
  
// Function for Query 2
void XorQuery(int x, int* curx)
{
    // Simply xor-ing all the number which
    // was asked to xor with the set elements.
    (*curx) = (*curx) ^ x;
}
  
// Function for Query 3
void MinXor(int x, int trie[100][2])
{
    int ans = 0, p = 0;
  
    // Finding the minimum element by checking 
    // if x[i] bit is same with trie element.
    for (int i = Maxbits - 1; i >= 0; i--) 
    {
        bool Currbit = (x >> i & 1);
  
        if (trie[p][Currbit])
            p = trie[p][Currbit];
  
        else {
            p = trie[p][!Currbit];
            ans |= 1 << i;
        }
    }
  
    cout << ans << endl;
}
  
// Driver code
int main()
{
    int sz = 1;
    int curx = 0;
    int trie[100][2] = { 0 };
  
    // Initialising the trie
    Insert(0, 0, &sz, trie);
  
    // Calling the Query
    MinXor(curx, trie);
    Insert(7, curx, &sz, trie);
    MinXor(curx, trie);
    XorQuery(4, &curx);
    XorQuery(8, &curx);
    XorQuery(3, &curx);
    Insert(10, curx, &sz, trie);
    Insert(3, curx, &sz, trie);
    MinXor(curx, trie);
    XorQuery(1, &curx);
  
    return 0;
}
输出:
0
0
3