给定一个初始元素为 0 的集合 S,即 S = { 0 }。任务是在给出 Q 个查询时执行每个查询,并在每个类型 3 的查询后打印答案。
我们可以执行三种类型的查询操作:
- 1 X:我们可以将 X 添加到集合 S 中。
- 2 Y:对于每个元素 i,执行 i ⊕ Y。
- 3:求集合的最小元素。
例子:
Input: Q = 10,
3
1 7
3
2 4
2 8
2 3
1 10
1 3
3
2 1
Output: 0 0 3
Explanation:
For the given 10 queries, the changes in the set for each query is as follows:
- The minimum is 0.
- The number 7 added to S –> {0, 7}.
- The minimum is still 0.
- All of the numbers in S are changed to their xor with 4 –> {4, 3}.
- All of the numbers in S are changed to their xor with 8 –> {12, 11}.
- All of the numbers in S are changed to their xor with 3 –> {15, 8}.
- The number 10 added to S –> {15, 8 ,10}.
- The number 3 added to S –> {15, 8, 10, 3}.
- The minimum is now 3.
- All of the numbers in S are changed to their xor with 1 –> {14, 9, 11, 2}.
Input: Q = 6
3
1 7
3
1 4
2 8
3
Output: 0 0 8
先决条件:尝试。
方法:
我们将尝试使用最小异或值对问题的特里方法来解决这个问题。
- 因此,在这个问题中,我们有一个二进制特里树和一个整数 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 的元素进行异或的所有数字。- 对于查询 2 ,与 xi 异或。
我们不会将树中的每个元素与 xi 进行异或。相反,我们将只更新 x = XOR(x, xi) - 对于查询 3 ,获取最小元素。
到目前为止,我们应该用 X 对整个数组进行异或运算。
所以,现在我们只需要使用上述方法计算集合中所有元素与 X 异或得到的最小值。 - 对于查询 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。
- 对于查询 2 ,与 xi 异或。
下面是这种方法的 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