参考此处的问题挑战: Link
#include <iostream>
using namespace std;
int main() {
int T,*x,i,j,k,a,res,pres;
long Q,N,p,q;
cin>>T;
for(k=0;k<T;k++)
{
cin>>N>>Q;
x=new int[N];
for(i=0;i<N;i++)
{
cin>>x[i];
}
for(i=0;i<Q;i++)
{
pres=-999;
cin>>a>>p>>q;
for(j=p-1;j<q;j++)
{
res=a xor x[j];
if(pres<res)
{
pres=res;
}
}
cout<<pres<<endl;
}
delete [] x;
}
return 0;
}
我在更大的问题(N = 100000)(N,Q,T最大值)上超出时间限制(暗示问题可以优化)。我想我需要使用某种预处理来优化算法。对于整个问题,我的解决方案是O(NQT)。该问题需要针对查询中给定限制的所有可能XOR进行评估。所以,问题需要(q-p)[可以在最大N]次查询。我无法想办法避免这种情况。一个命中或方向将非常感激。我正在考虑以某种方式实现堆,以便它从堆中减去查询a并且使最大堆看到最大差异和密度。但这也需要O(NQT)
答案 0 :(得分:1)
我不认为摆弄你写的东西会让你受到很多速度的影响。你想要一个时间复杂度更高的东西。
从这个问题来看,我假设他们想要每个查询的O(log N)。我最初的想法是segment tree,但我找不到使用它们来最大化a ^ x[i]
的方法。
我相信你应该使用所有数字都小于2^15
的事实。另外需要注意的是,您希望最大化xor
操作。假设你有(二进制)
a = b_1 b_2 ... b_n
您要么所有x[j]
与p <= j <= q
的最高有效位等于b_1
,要么有一些x[j]
,其中最重要的位是b_1
的补充。这是因为b xor ~b = 1
b in {0,1}
。您只选择MSB为j
补码的b_1
,然后继续下一位(对应b_2
)。
问题在于,这种情况的蛮力实施比您已经在做的更糟糕,但它可能会帮助您更快地实施。
答案 1 :(得分:0)
一些提示:
cin
的所有调用都无法衡量此代码的性能。你应该提前从文件中读取所有数据。x
,使用malloc
分配一次,并在需要时调用realloc
以使缓冲区更长。内存分配可能会减慢速度。内部循环非常简单,因此编译器可以对其进行矢量化。通过查看反汇编确保实际发生这种情况。如果没有,请使用SSE内在函数一次处理4个或8个8个元素。
答案 2 :(得分:0)
以下是修改后的代码以及我在评论中提出的建议。
在性能敏感的代码中避免使用C ++ iostream。 (FWIW,一般避免iostreams)
尽可能避免分配/解除分配。在下面的代码中,vector::resize
会
注意向量始终至少具有所需的空间。
不是性能,而是可读性:使用空间aronud运算符。声明变量关闭
到他们使用的地方。
#include <cstdio>
#include <vector>
#include <algorithm>
int main() {
int T;
std::vector<int> x;
std::scanf ("%d", &T);
for (int k = 0; k < T ; ++k) {
int N, Q;
std::scanf ("%d%d", &N, &Q);
x.resize (N);
for (int i = 0; i < N; ++i)
std::scanf ("%d", &x[i]);
for (int i = 0; i < Q; ++i) {
int a, p, q;
std::scanf ("%d%d%d", &a, &p, &q);
int pres = -999;
for(int j = p - 1; j < q; ++j)
pres = std::max (pres, a ^ x[j]);
std::printf ("%d\n", pres);
}
}
return 0;
}