Алгоритм: найти максимальное значение Xor в массиве для различных интервалов, учитывая N входов, и p, q, где 0 <= p <= i <= q <= N

0

оператор проблемы следующий:

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 на самом деле, что медленно или есть что-то еще, что мне не хватает?

  • 0
    Форматированный ввод с помощью cin и operator>> может быть медленным, но также может форматировать вывод ( cout << ... ). Вы, вероятно, обнаружите, что большую часть времени, которое требуется для выполнения этой функции, это просто ввод и вывод, а не битовые манипуляции.
  • 1
    Нет, проблема не в чтении со стандартного ввода. Да, вы что-то упустили. А именно, реализация тупого, тривиального алгоритма грубой силы не является целью этого конкурса. Вы должны придумать более быстрый алгоритм.
Показать ещё 8 комментариев
Теги:
algorithm
bit-manipulation
cin

2 ответа

0

Я потратил некоторое время на то, чтобы решить эту проблему, и это похоже на то, что вы можете найти ее в контексте различных соревнований по программированию. Хотя подход грубой силы интуитивно понятен, на самом деле он не решает проблему, поскольку она слишком медленная. В проблеме есть несколько недостатков, которые вам нужно спрогнозировать, чтобы написать более быстрый алгоритм:

  • вход состоит из максимальных 100 тыс. номеров, но есть только 32768 (2 ^ 15) возможных номеров
    • для каждого входного массива есть Q, max 50k, тестовые примеры; каждый тестовый случай состоит из 3 значений: a, pi и qi. Поскольку 0 <= a <2 ^ 15 и есть 50k случаев, вероятность того же значения снова появится.

Я нашел 2 идеи для решения проблемы: splitting the input in sqrt(N) интервалы и building a segment tree (хорошее объяснение для этих подходов можно найти здесь)

Самая большая проблема заключается в том, что для каждого тестового примера вы можете иметь разные значения для a, и это сделало бы предыдущие результаты бесполезными, так как вам нужно вычислить max (a ^ x [i]) для небольшого числа тестовых случаев. Однако, когда Q достаточно велико и значение a повторяется, использование предыдущих результатов может быть возможным.

Я вернусь с фактическими результатами, как только закончу реализацию обоих методов

  • 0
    Ух, есть только 32к уникальных номеров? Как я это пропустил? Я бы на самом деле пошел на prefix tree . Я не вижу немедленной выгоды от его использования, когда ваш набор предметов постоянен. И, на самом деле, я не вижу никакой выгоды в использовании его для поиска. Я предложил сочетание prefix tree (которое находит вам решение) с аннотацией о «сегментах» (которая отфильтровывает ключи, которые отсутствуют. -of-диапазон).
  • 0
    есть только ~ 32k уникальных значений для a, но вам нужно вычислить max (a ^ x [i]); если вы искали только max (x [i]), то вы могли бы построить только одно дерево.
Показать ещё 31 комментарий
0

XOR переворачивает биты. Максимальный результат XOR равен 0b11111111.

Чтобы получить лучший результат

  • если "a" на i-м месте имеет 1, тогда вы должны XOR его с ключом, который имеет i-й бит = 0
  • если "a" на i-м месте имеет 0, тогда вы должны XOR его с ключом, который имеет i-й бит = 1

говоря просто, для бит B вам нужно! B

Еще одна очевидная вещь заключается в том, что биты более высокого порядка важнее, чем бит более низкого порядка.

То есть:

  • если "a" на самом высоком месте имеет B, и вы нашли ключ с самым высоким битом =! 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.

  • 0
    максимум a ^ xi получается, если xi = not (a), поскольку a ^ not (a) = FFFF; Я могу найти некоторую логику для работы с битами. НО для того, чтобы это работало, числа должны были быть отсортированы, иначе я все еще сканирую все входы, которые я уже делаю ...
  • 0
    «Если вы аннотируете узлы дерева с низкими / высокими индексными диапазонами его подэлементов» - проблема в том, что на большинстве уровней в дереве - при условии случайного ввода - пропорция значений N охватывает диапазон, стремящийся к (N-1) / Н ... действительно не очень эффективный фильтр.
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню