两段异或和的最大值 二进制TRIE图表达式 XOR CodeChef Nikitosh and xor

4 篇文章 0 订阅
3 篇文章 0 订阅

找出下面式子的最大值:
(A[l1] ⊕ A[l1 + 1] ⊕ · · · ⊕ A[r1]) + (A[l2] ⊕ A[l2 + 1] ⊕ · · · ⊕ A[r2])
其中,1 ≤ l1 ≤ r1 < l2 ≤ r2 ≤ N。
式中 x ⊕ y 表示 x 和 y 的 按位异或

PROBLEM LINK:

Practice
Contest

Author: Yurii Rebryk
Tester: Kevin Atienza
Editorialists: Pushkar Mishra and Suhash Venkatesh

DIFFICULTY:

Medium

PREREQUISITES:

Tries, Properties of Bitwise XOR

PROBLEM:

Given is an array  A  containing numbers in the range 0 to  109 . We have to find  l1 r1 l2  and  r2  ( l1r1<l2r2 ) such that ( A[l1]A[l1+1]A[r1] ) + ( A[l2]A[l2+1]A[r2] ) is maximised. Here  xy  refers to Bitwise XOR of  x  and  y .

EXPLANATION:

Subtask 1
Let's start off by thinking of the simplest algorithm that we can. We we will then optimise it step by step by making certain observations.
So, the simplest thing to do is to implement what the problem says. We can run four loops, one each for  l1 r1 l2  and  r2 . This gives us an  O(N4)  algorithm which will exceed the time limit for all the subtasks.

How can we optimise this? Let's make an observation. If we know for each  i  =  1  to  N , the maximum value we can get for ( A[l1]A[l1+1]A[r1] ) and ( A[l2]A[l2+1]A[r2] ) such that  r1i  and  i<l2 , then we can tell the answer in  O(N)  by simply taking the maximum of the sum of the two terms over all  i .

What remains now is to calculate efficiently for each  i  the max ( A[l1]A[l1+1]A[r1] ) and ( A[l2]A[l2+1]A[r2] ) such that  r1i  and  i<l2 . Let's call the two terms  lbest[i]  and  rbest[i] respectively. For calculating  lbest[i] , we iterate from  j  =  i  to  1  and find the  j  such that  val  = ( A[j]A[j+1]A[i] ) is maximised. Then,  lbest[i]  =  max(lbest[i1],val) . Similarly, we can fill the array  rbest .

Calculating the arrays  lbest  and  rbest  require  O(N2)  time. After that, the answer can be computed in  O(N) . For this subtask, an  O(N2)  solution will pass.

Subtask 2
We need to somehow speed up the calculation of arrays  lbest  and  rbest . Up till now, we haven't utilised any property of XOR operation in our solution. Let's try to optimise our algorithm using the following property:
Let  cumul[i]  = ( A[1]A[2]A[i] ).
Then for some  ji cumul[j1]cumul[i]  = ( A[j]A[j+1]A[i] ).
The proof behind this is left to the reader as a simple exercise.

We can now say that  lbest[i]  =  max(lbest[i1],val)  where  val  = maximum of ( cumul[j1]cumul[i] ) for  j  =  1  to  i .

Calculating  lbest  this way still takes  O(N2) . For  i  =  1  to  N , we need to somehow optimise finding the index  j  such that ( cumul[j1]cumul[i] ) is maximum. If we can do it in  O(logA[i]) , then we can compute the array  lbest (and analogously,  rbest  too) in  O(NlogAmax) .

We can use Tries to get the required complexity. We will keep a trie which holds the binary representation of elements in the array  cumul . While processing for  i  from  1  to  N , we will first use the trie to get the value which is maximum of ( cumul[j1]cumul[i] ) for  1ji , and then insert  cumul[i]  into the trie. This will allow us to calculate  lbest  in the required complexity. Similarly, we can calculate  rbest  also.

Inserting into a trie is a standard operation. Let us look at how we do the other operation, i.e., for a value  x , finding the value  y  in the trie such that  xy  is maximised. Since, the trie stores binary representations of numbers, we first convert  x  to its binary representation. Then, we can go down the trie and for each bit in the representation of  x , we try to find whether bit of opposite value exists or not. It is easy to see why we seek opposite; because  11  and  00 0  while  01  =  1 .

COMPLEXITY:

O(NlogAmax)

SAMPLE SOLUTIONS:

Author
Tester
Editorialist

#include <stdio.h>
 
#define NMAX 500000
 
int A[NMAX], N;
int maxleft[NMAX], maxright[NMAX];
 
void ReadInput() {
	scanf("%d", &N);
	for (int i = 1; i <= N; i++) scanf("%d", &A[i]);
}
 
#define MAX_TRIE_NODES 20000000
 
int next[MAX_TRIE_NODES][2];
int nnodes;
 
void ClearTrie() {
	nnodes = 1;
	next[1][0] = next[1][1] = 0;
}
 
void InsertInTrie(int x) {
	for (int bit = 30, node = 1; bit >= 0; bit--) {
		int dir = 0;
		if ((x & (1 << bit)) > 0) dir = 1;
		if (next[node][dir] == 0) {
			nnodes++;
			next[node][dir] = nnodes;
			next[nnodes][0] = next[nnodes][1] = 0;
		}
		node = next[node][dir];
	}
}
 
int GetMax(int x) {
	int ans = 0;
	for (int bit = 30, node = 1; bit >= 0; bit--) {
		int dir = 0;
		if ((x & (1 << bit)) > 0) dir = 1;
		if (next[node][1 - dir] > 0) {
			ans |= (1 << bit);
			dir = 1 - dir;
		}
		node = next[node][dir];
	}
	return ans;
}
 
int main() {
	//freopen("y.txt", "r", stdin);
	ReadInput();
	ClearTrie();
	InsertInTrie(0);
	int i, sxor = 0;
	maxleft[0] = 0;
	for (i = 1; i <= N; i++) {
		sxor ^= A[i];
		maxleft[i] = GetMax(sxor);
		if (maxleft[i - 1] > maxleft[i]) maxleft[i] = maxleft[i - 1];
		InsertInTrie(sxor);
		//fprintf(stderr, "maxleft(%d)=%d\n", i, maxleft[i]);
	}
	ClearTrie();
	InsertInTrie(0);
	sxor = 0;
	maxright[N + 1] = 0;
	for (i = N; i >= 1; i--) {
		sxor ^= A[i];
		maxright[i] = GetMax(sxor);
		if (maxright[i + 1] > maxright[i]) maxright[i] = maxright[i + 1];
		InsertInTrie(sxor);
		//fprintf(stderr, "maxright(%d)=%d\n", i, maxright[i]);
	}
 
	unsigned int ans = 0, cans;
	for (i = 2; i <= N; i++) {
		cans = (unsigned int) maxleft[i - 1] + (unsigned int) maxright[i];
		if (cans > ans) ans = cans;
	}
	
	printf("%u\n", ans);
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值