问题陈述如下:
Xorq发明了一种加密算法,该算法广泛使用按位XOR运算。该加密算法使用一系列非负整数x1,x2,... xn作为关键字。为了有效地实现该算法,Xorq需要为给定的整数a,p和q找到(a xor xj)的最大值,使得p <= j <= q。帮助Xorq实现此功能。
输入
第一行输入包含单个整数T(1 <= T <= 6)。 T测试案例如下。
每个测试用例的第一行包含由单个空格分隔的两个整数N和Q(1 <= N <= 100,000; 1 <= Q <= 50,000)。下一行包含由单个空格(0 <= xi <2 ^ 15)分隔的N个整数x1,x2,... xn。接下来的Q行中的每一行描述由三个整数ai,pi和qi组成的查询(0 <= ai&lt; 2 ^ 15,1 <= pi&lt; = qi&lt; = N)。
输出
对于每个查询,打印(ai xor xj)的最大值,使pi&lt; = j&lt; = qi在一行中。
int xArray[100000];
cin >>t;
for(int j =0;j<t;j++)
{
cin>> n >>q;
//int* xArray = (int*)malloc(n*sizeof(int));
int i,a,pi,qi;
for(i=0;i<n;i++)
{
cin>>xArray[i];
}
for(i=0;i<q;i++)
{
cin>>a>>pi>>qi;
int max =0;
for(int it=pi-1;it<qi;it++)
{
int t = xArray[it] ^ a;
if(t>max)
max =t;
}
cout<<max<<"\n" ;
}
除了问题文本中所述的那些(数字未分类)之外,不得做出任何其他假设。 代码功能齐全,但速度不够快;从stdin那里读到的确很慢或者还有什么我想念的吗?
答案 0 :(得分:0)
XOR翻转位。 XOR的最大结果是0b11111111。
获得最佳结果
简单地说,对于你需要的B位!B
另一个显而易见的事情是高阶位比低阶位更重要。
那是:
这会将您的数字量平均减少一半。
如何从所有密钥构建一个巨大的二叉树,并按树的顺序从树中对它们进行排序,从MSB到LSB。然后,将A从MSB逐位切换到LSB将告诉您接下来要采用哪个左右分支以获得最佳结果。当然,这会忽略PI / QI限制,但肯定会给你最好的结果,因为你总是选择i级的最佳可用位。
现在,如果您注释其子元素的低/高索引范围的树节点(在构建树时仅执行一次),那么稍后在查询案例A-PI-QI时您可以使用它来过滤掉不属于索引范围的分支。
关键是如果您按照MSB-> LSB位顺序排序树级别,那么在“上级节点”执行的决策可以保证您当前处于最佳分支中,并且它将保持即使所有的分支都是最差的:
处于第3级,
的结果0b111?????
然后可以扩展到
0b11100000
0b11100001
0b11100010
等等,但即使是?????扩张不佳,总体结果仍然大于
0b11011111
如果您甚至在第3级选择了另一个分支,这将是最好的结果。
我绝对不知道准备树成本需要多长时间,但查询它有32位的A-PI-QI似乎是N次比较和跳跃的32倍,肯定比随机迭代0更快100000次和xor / maxing。而且由于您有多达50000个查询,因此构建此类树实际上可能是一项很好的投资,因为每个密钥集都会构建一次这样的树。
现在,最好的部分是你实际上不需要整棵树。您可以仅从前两个或四个或八个位构建此类,并使用节点中的索引范围将xor-max循环限制为较小的部分。在最坏的情况下,你最终会得到与PiQi相同的范围。充其量只能归结为一个元素。
但是,看看最大的N个键,我认为整个树实际上可能适合内存池,你可能会在没有任何xor-maxing循环的情况下离开。
答案 1 :(得分:0)
我花了一些时间来研究这个问题,并且它可以在各种编程竞赛的背景下找到它。虽然蛮力方法很直观,但它并没有真正解决挑战,因为它太慢了。 为了编写更快的算法,你需要推测这个问题有一些限制因素:
我找到了2个解决问题的方法:splitting the input in sqrt(N)
区间和building a segment tree
(可以找到这些方法的一个很好的解释here)
最大的问题是,对于每个测试用例,你可以为a设置不同的值,这会使以前的结果无用,因为你需要计算max(a ^ x [i]),少数测试用例。但是,当Q足够大且值a重复时,可以使用以前的结果。
一旦完成两种方法的实施,我将回到实际结果