两段异或和的最大值 二进制TRIE图表达式 XOR CodeChef Nikitosh and xor
2015-09-22 16:23
453 查看
找出下面式子的最大值:
(A[l1] ⊕ A[l1 + 1] ⊕ · · · ⊕ A[r1]) + (A[l2] ⊕ A[l2 + 1] ⊕ · · · ⊕ A[r2])
其中,1 ≤ l1 ≤ r1 < l2 ≤ r2 ≤ N。
式中 x ⊕ y 表示 x 和 y 的 按位异或
https://discuss.codechef.com/questions/74773/rebxor-editorial
PROBLEM LINK:
PracticeContest
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 containingnumbers in the range 0 to 109.
We have to find l1, r1, l2 and r2 (l1≤r1<l2≤r2)
such that (A[l1]⊕A[l1+1]⊕⋯⊕A[r1])
+ (A[l2]⊕A[l2+1]⊕⋯⊕A[r2])
is maximised. Here x⊕y refers
to Bitwise XOR of x and y.
EXPLANATION:
Subtask 1Let'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 r1≤i 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 r1≤i 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[i−1],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 j≤i, cumul[j−1]⊕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[i−1],val) where val =
maximum of (cumul[j−1]⊕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[j−1]⊕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[j−1]⊕cumul[i])
for 1≤j≤i,
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 x⊕y 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 1⊕1 and 0⊕0= 0 while 0⊕1 = 1.
COMPLEXITY:
O(NlogAmax)
SAMPLE SOLUTIONS:
AuthorTester
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; }
相关文章推荐
- jQuery 实现最简单的form表单提交 Loding 功能
- offsetLeft与style.left区别
- ASP.NET本质论阅读----线程与异步
- poj2586
- Quartz2D-图形上下文栈
- 树莓派与继电器
- plupload 使用案例 及 中文文档
- iOS---XCode7 + IOS9 问题及解决方案
- Building System之编译前的准备工作
- MySQL的备份与还原
- 蜻蜓fm面试
- 一键安装lnmp之php
- 对Django框架架构和Request/Response处理流程的分析
- 黑马程序员——IOS学习笔记(Foundation框架(二))
- jdbc sid 与 service name 使用方法及区别
- 网页性能管理详解
- C++设计模式——抽象工厂模式
- RocketMQ(二)——TopicPublicInfo
- ewebeditor上传文件大小及在线编辑器jsp版使用心得
- 基础总结篇之一:Activity生命周期[转]