оператор проблемы следующий:
Xorq изобрел алгоритм шифрования, который широко использует побитовые операции XOR. Этот алгоритм шифрования использует последовательность неотрицательных целых чисел x1, x2,... xn в качестве ключа. Чтобы эффективно реализовать этот алгоритм, Xorq должен найти максимальное значение для (xor xj) для заданных целых чисел a, p и q таких, что p <= j <= q. Помогите Xorq реализовать эту функцию.
вход
Первая строка ввода содержит одно целое число T (1 <= T <= 6). T испытаний.
Первая строка каждого тестового примера содержит два целых числа N и Q, разделенные одним пространством (1 <= N <= 100 000; 1 <= Q <= 50 000). Следующая строка содержит N целых чисел x1, x2,... xn, разделенных одним пространством (0 <= xi <2 ^ 15). Каждая из следующих Q-строк описывает запрос, который состоит из трех целых чисел ai, pi и qi (0 <= ai <2 ^ 15, 1 <= pi <= qi <= N).
Вывод
Для каждого запроса напечатайте максимальное значение для (ai xor xj), такое, что pi <= j <= 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 на самом деле, что медленно или есть что-то еще, что мне не хватает?
Я потратил некоторое время на то, чтобы решить эту проблему, и это похоже на то, что вы можете найти ее в контексте различных соревнований по программированию. Хотя подход грубой силы интуитивно понятен, на самом деле он не решает проблему, поскольку она слишком медленная. В проблеме есть несколько недостатков, которые вам нужно спрогнозировать, чтобы написать более быстрый алгоритм:
Я нашел 2 идеи для решения проблемы: splitting the input in sqrt(N)
интервалы и building a segment tree
(хорошее объяснение для этих подходов можно найти здесь)
Самая большая проблема заключается в том, что для каждого тестового примера вы можете иметь разные значения для a, и это сделало бы предыдущие результаты бесполезными, так как вам нужно вычислить max (a ^ x [i]) для небольшого числа тестовых случаев. Однако, когда Q достаточно велико и значение a повторяется, использование предыдущих результатов может быть возможным.
Я вернусь с фактическими результатами, как только закончу реализацию обоих методов
prefix tree
. Я не вижу немедленной выгоды от его использования, когда ваш набор предметов постоянен. И, на самом деле, я не вижу никакой выгоды в использовании его для поиска. Я предложил сочетание prefix tree
(которое находит вам решение) с аннотацией о «сегментах» (которая отфильтровывает ключи, которые отсутствуют. -of-диапазон).
XOR переворачивает биты. Максимальный результат XOR равен 0b11111111.
Чтобы получить лучший результат
говоря просто, для бит B вам нужно! B
Еще одна очевидная вещь заключается в том, что биты более высокого порядка важнее, чем бит более низкого порядка.
То есть:
Это сокращает ваше количество чисел наполовину "в среднем".
Как насчет создания огромного двоичного дерева из всех ключей и упорядочения их в дереве их битами, от MSB до LSB. Затем, сокращая бит "бит" от MSB до LSB, вы скажете, какая ветка слева направо, чтобы получить лучший результат. Конечно, это игнорирует пределы PI/QI, но, несомненно, даст вам лучший результат, так как вы всегда выбираете лучший доступный бит на i-м уровне.
Теперь, если вы аннотируете узлы дерева с низкими/большими индексами его подэлементов (выполняются только один раз при построении дерева), а затем при запросе на случай A-PI-QI вы можете использовать это для отфильтрованных ветвей, которые делают не попадают в диапазон индексов.
Дело в том, что если вы заказываете древовидные уровни, такие как MSB-> порядок бит LSB, то решение, выполняемое на "верхних узлах", может гарантировать вам, что в настоящее время вы находитесь в наилучшей возможной ветки, и она будет сохраняться, даже если все худшие были:
Будучи на уровне 3, результат
0b111?????
могут быть затем расширены
0b11100000
0b11100001
0b11100010
и так далее, но даже если слабо развиты, общий результат еще больше, чем
0b11011111
что было бы наилучшим возможным результатом, если бы вы даже выбрали другую ветвь на третьем уровне.
Я не знаю, как долго будет готовить стоимость дерева, но запрашивать его для A-PI-QI, который имеет 32 бита, похоже, что-то вроде 32-кратного N-сравнений и прыжков, конечно, быстрее, чем повторять случайным образом 0-100000 раз и исключающее /Maxing. И так как у вас есть до 50000 запросов, то построение такого дерева действительно может быть хорошей инвестицией, так как такое дерево будет строиться один раз за набор ключей.
Теперь лучше всего то, что вам действительно не нужно все дерево. Вы можете построить такие, например, первые два или четыре или восемь бит, и использовать диапазоны индексов от узлов, чтобы ограничить цикл xor-max меньшим. В худшем случае вы окажетесь в том же диапазоне, что и PiQi. В лучшем случае это будет до одного элемента.
Но, глядя на клавиши max N, я думаю, что все дерево может действительно вписаться в пул памяти, и вы можете уйти без какого-либо цикла xor-maxing.
cin
иoperator>>
может быть медленным, но также может форматировать вывод (cout << ...
). Вы, вероятно, обнаружите, что большую часть времени, которое требуется для выполнения этой функции, это просто ввод и вывод, а не битовые манипуляции.