给定具有初始元素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
先决条件:特里。
方法:
我们将尝试使用最小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运算的所有数字。- 对于查询2 ,与xi进行XOR。
我们不会将trie中的每个元素与xi进行XOR。相反,我们将只更新x = XOR(x,xi) - 对于查询3 ,获取最小元素。
到目前为止,我们应该已经使用X对整个数组进行了XOR运算。
因此,现在我们将使用上述方法,通过对集合中所有元素与X进行XOR运算来计算最小值。 - 对于查询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。
- 对于查询2 ,与xi进行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