В связи с проблемой проблемы здесь: Ссылка
#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 maxing out). Я полагаю, что мне нужно оптимизировать алгоритм, используя некоторую предварительную обработку. Мое решение - O (NQT) для всей проблемы. Проблема должна будет оценивать для всех возможных XOR для заданных лимитов в запросе. Таким образом, проблема должна будет идти (qp) [Может быть в max N] раз для запроса. Я не могу понять, как избежать этого. Хит или направление было бы действительно оценено. Я думаю о реализации кучи как-то, так что он вычитает запрос a из кучи, и den делает максимальную кучу, чтобы увидеть максимальную разницу и den xors. Но это тоже займет O (NQT)
Я не думаю, что возиться с тем, что вы написали, поможет вам в скорости. Вы хотите что-то с лучшей временной сложностью.
Из вопроса я предполагаю, что они хотят что-то, что есть O (log N) для каждого запроса. Моя первоначальная мысль была деревом сегментов, но я не мог найти способ использовать их для максимизации 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}
. Вы выбираете только те j
для которых MSB является дополнением к b_1
, и продолжайте следующий бит (соответствующий b_2
).
Проблема в том, что выполнение этой грубой силы хуже того, что вы уже делаете, но это может помочь вам в более быстрой реализации.
Здесь измененный код с предложениями, которые я сделал в комментариях.
Избегайте C++ iostreams в коде, чувствительном к производительности. (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;
}
Некоторые советы:
cin
делают невозможным измерение производительности этого кода. вы должны прочитать все данные заранее из файлов.x
каждый внешний вид, выделяйте один раз с помощью malloc
и вызывается realloc
чтобы сделать буфер длиннее, если это необходимо. Распределение памяти может замедлить работу.Внутренний цикл очень прост, поэтому компилятор может его векторизовать. Убедитесь, что это действительно происходит, глядя на разборку. Если нет, используйте встроенные функции SSE для работы по 4 или 8 8 элементам за раз.
using namespace std;
? Сначала очистите код и получите огромные постоянные факторы.