3741. Subarray with maximum XOR

 

Given an array of integers. Find the subarray with maximum XOR.

 

Input. The first line contains the size of array n (n ≤ 105). Second line contains n integers a1a2, ..., an (0 ≤ ai ≤ 1018).

 

Output. Print such l and r for which the value al xor al+1 xor ... xor ar is maximum among all possible subarrays [lr] (1 ≤ lrn). Then in the same line print the value of maximum XOR.

 

Sample input

Sample output

7

2 8 12 4 9 2 3

4 6 15

 

 

SOLUTION

trie

 

Algorithm analysis

Consider the following series of numbers:

b0 = 0,

b1 = a1,

b2 = a1 xor  a2,

...,

bn = a1 xor  a2 xor … xor an

The numbers b0, b1b2, ..., bn will be sequentially inserted into the binary trie. Let b0, b1b2, ..., bi are already in the trie. Find a number bk (k < i) such that bk xor bi is maximal. Given that bk xor bi = ak+1 xor … xor ai, with this operation we are looking for a subarray with the maximum XOR that ends in ai. Among all such maxima, we look for the largest one, which is the answer.

 

Algorithm realization

Declare a binary trie, the sons of the trie vertices correspond to bits 0 and 1. The size of the trie is stored in TrieSize variable.

 

#define MAX 100001

 

int trie[MAX * 60][2];

long long b[MAX], mx;

int num[MAX * 60], TrieSize;

 

The function Insert inserts a number x = b[pos] into the trie.

 

void Insert(int pos)

{

  int v = 0;

  long long x = b[pos];

 

Inserting a number into a trie starts with the high bits.

 

  for (int i = 62; i >= 0; i--)

  {

 

The variable bit contains the i-th bit of number x.

 

    int bit = x & (1LL << i) ? 1 : 0;

 

If there is no path along the bit in the trie, we create a new vertex.

 

    if (trie[v][bit] == -1)

      trie[v][bit] = TrieSize++;

 

Move further along the trie.

 

    v = trie[v][bit];

  }

 

Vertex v is final for the number x = b[pos]. Store in num[v] the index pos of array b.

 

  num[v] = pos;

}

 

The function Find returns the index pos of array b for which x xor bpos is maximum.

 

int Find(long long x)

{

  int i, v = 0;

  for (i = 62; i >= 0; i--)

  {

 

Move in the trie along the bits that are reverse to the binary representation of the number x.

 

    int bit = x & (1LL << i) ? 0 : 1; // reverese bit

 

If the movement along the trie is impossible, move along another bit.

 

    if (trie[v][bit] == -1) bit ^= 1;

    v = trie[v][bit];

  }

 

Return the index pos of array b, that corresponds to the vertex v of the trie.

 

  return num[v];

}

 

The main part of the program. Read the input data. Initially trie contains one vertex (TrieSize = 1). Initialize the trie and num arrays.

 

scanf("%d", &n);

TrieSize = 1;

memset(trie, -1, sizeof(trie));

memset(num, -1, sizeof(num));

 

Insert to the trie b0 = 0. Compute in the variable mx, the maximum XOR value on subarray.

 

b[0] = 0;

Insert(0);

mx = 0;

 

Insert the rest of the sequence b1b2, ..., bn into the trie.

 

for (i = 1; i <= n; i++)

{

 

Read the value of ai = val.

 

  scanf("%lld", &val);

 

Compute bi = bi-1 xor ai.

 

  b[i] = b[i - 1] ^ val;

 

Insert the value bi into the trie.

 

  Insert(i);

 

Find such value of k, that bk xor bi is maximum. Subarray with maximum XOR that ends at position i starts at k + 1. Not that bk xor bi = ak+1 xor … xor ai.

 

  k = Find(b[i]);

 

Among all the values ak+1 xor … xor ai (i = 1, 2, …, n) find maximum.

 

  if ((b[k] ^ b[i]) > mx)

  {

    mx = b[k] ^ b[i];

    l = k + 1;

    r = i;

  }

}

 

Print the boundaries l and r of desired subarray and XOR value on it.

 

printf("%d %d %lld\n", l, r, mx);