📜  对给定集合的异或查询

📅  最后修改于: 2021-09-03 03:12:31             🧑  作者: Mango

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

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

例子:

先决条件:尝试。

方法:

我们将尝试使用最小异或值对问题的特里方法来解决这个问题。

  • 因此,在这个问题中,我们有一个二进制特里树和一个整数 x,我们必须找到 XOR(x, y) 的最小值,其中 y 是特里树中的某个整数。
  • 现在,为了解决这个问题,我们将从最高有效位到最低有效位。
  • 假设我们在第 i 位:
    如果 x[i] 是 1,我们将沿着有 1 的特里树的路径走下去。
    如果 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 的元素进行异或的所有数字。
    1. 对于查询 2 ,与 xi 异或。
      我们不会将树中的每个元素与 xi 进行异或。相反,我们将只更新 x = XOR(x, xi)
    2. 对于查询 3 ,获取最小元素。
      到目前为止,我们应该用 X 对整个数组进行异或运算。
      所以,现在我们只需要使用上述方法计算集合中所有元素与 X 异或得到的最小值。
    3. 对于查询 1 ,插入 ai。
      我们不会将 ai 插入到树中,而是 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

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live