Please subscribe to the official Codeforces channel in Telegram via the link https://t.me/codeforces_official. ×

alt_438's blog

By alt_438, history, 2 years ago, In English

You are given an array of size N. you are also given M queries with each query Qi having a number k. you can perform the following operation during each query: XOR each element of A with k. Now,the answer to the query is the mex of A.

let R be an array of size M.the with element in R must be the answer to the ith query. your task is to return R. Note:-> A returns to its original state after each query. Constraints:-> 1<=N<=10^5 1<=M<=10^5

  • Vote: I like it
  • +10
  • Vote: I do not like it

»
2 years ago, # |
Rev. 3   Vote: I like it +6 Vote: I do not like it

Oh, I had this task on my lesson 3 or 4 months ago. It may sound strange, but in this task you have to use trie. A tough task, tbh.

First of all, we need to find MEX without xoring numbers using the trie. Do to it, we are gonna use DFS on trie. Trie will be built on numbers as binary strings (all the strings will have a size of 31). Let's say, the DFS is at some vertex and it's children are v for 0 and u for 1. Let's define count(x) as amount of numbers from the array that are lying in x's subtree. Then, if count(v) is less then possible amount of strings in it's subtree, it means that MEX is somewhere in v's subtree. Otherwise, it's in u's subtree.

Ok, we now are able to find MEX without the changes using the trie. How are we gonna deal with the XOR queries? First of all, let's look at logical XOR.

0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0

We can interprete it as following: if we xor a logical value with a 1, it becomes the opposite value. Otherwise, it doesn't change. What does that mean to a trie? Well, let x be the value we are xoring the array with. Then let's look at all the vertexes in trie. Let N(x) be index of bit that relates to vertex b; Let x[i] be i-th bit of x. Then for each vertex v in trie we should check whether x[N(v) + 1] == 1. If it is so, we simply need to swap v's children (and their subtrees). It can be done by swapping their pointers, btw. But it still works in O(N) on XOR query, which is too slow.

To make our solution faster, we need to notice that we don't actually need to swap it at all. We can simply check whether children need to be swapped while calculating the XOR. If so, we will firstly try to go in the 1-subtree. And if it's full, we'll go to the 0-subtree.

The last thing we need to do is to find out how to deal not with one xor query, but with many of those. Well, associativity of xor says that a ^ (b ^ c) == (a ^ b) ^ c. That means that a ^= b and a ^= c is equal to a ^= (b ^ c). That means that we can make a variable currXor = 0. When we receive a query of xoring the array with x, we simply do currXor ^= x. When we receive a MEX query, we will deal with it just as I explained above, but considering the x to xor with is equal to currXor.

  • »
    »
    2 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Oh, the last part of the solution is useless. I just saw that array returns to it's original state after every query.

  • »
    »
    2 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    Thanks a lot for amazing explanation,