Мерой похожести двух вирусов служит побитовое исключающее ИЛИ (XOR) их геномов: чем меньше XOR, тем более похожи вирусы.
В базе лежат геномы
[38, 18, 7, 52, 13, 25, 60, 3, 44, 29]
Найдите наименьший возможный XOR пары геномов, стоящих на разных позициях.
The similarity of two viruses is measured by the bitwise exclusive OR (XOR) of their genomes: the smaller the XOR, the more similar the viruses.
The database contains the genomes
[38, 18, 7, 52, 13, 25, 60, 3, 44, 29]
Find the smallest possible XOR of two genomes at distinct positions.
Подсказка / Hint
Для десяти чисел хватит перебора сорока пяти пар — приём из b1101, только вместо суммы XOR. Быстрый ход — тот же спуск по разрядам, что в мосте b1105, но в обратную сторону. А дальше подумай, как отвечать на такой запрос, если чисел $2 \cdot 10^5$ и они добавляются по одному.
With ten numbers, enumerating all forty-five pairs is enough; this is the technique from b1101, with XOR instead of addition. The fast approach uses the same bitwise descent as bridge problem b1105, but in the opposite direction. Then consider how to answer the query if there are $2 \cdot 10^5$ numbers arriving one by one.
Решение / Solution
Ответ для наших данных: 4 — пара $7$ и $3$: $7 \oplus 3 = 0111_2 \oplus 0011_2 = 0100_2 = 4$.
from itertools import combinations print(min(x ^ y for x, y in combinations(G, 2))) # 4
Перебор пар — это $O(n^2)$, здесь всего 45 пар. На олимпиадных ограничениях ($n$ до $2\cdot10^5$, числа до $2^{30}$) он не проходит, и нужен другой подход.
Правильное решение — префиксное дерево (бор) на битах.
Храним двоичные представления чисел в дереве как строки длины $K = 30$, от старших разрядов к младшим. При добавлении нового числа $X$ делаем два действия:
- Ищем в боре число $Y$, дающее минимальный XOR с $X$. Спускаемся от корня; на каждой глубине пытаемся пойти по тому же биту, что у $X$ — тогда в этом разряде XOR даст ноль. Если такого перехода нет, идём по единственному имеющемуся.
- Вставляем $X$ в бор.
Ответ поддерживаем как минимум по всем добавлениям.
Почему жадный спуск корректен. Пусть на глубине $d$ можно пойти двумя путями. Совпадение бита даёт в этом разряде ноль, несовпадение — единицу, то есть вклад $2^{K-d}$. Но по пункту блока «Мост» один старший разряд перевешивает все младшие вместе взятые, поэтому совпадение в старшем разряде выгоднее любого выигрыша во всех младших. Жадность оптимальна.
Сложность: $O(NK)$ по времени и памяти, где $K$ — число бит.
Работает правило из блока «Триггеры»: минимальный XOR всегда достигается на паре соседей в отсортированном порядке. Вот его вывод в две строки. Пусть $x < y < z$, и пусть $b$ — самый старший разряд, в котором $x$ и $z$ различаются: в нём у $x$ ноль, у $z$ единица, поэтому $x \oplus z \ge 2^{b}$. Все разряды старше $b$ у $x$ и $z$ совпадают, а $y$ лежит между ними, поэтому в старших разрядах $y$ совпадает с обоими; в самом разряде $b$ у $y$ стоит либо ноль, и тогда $x \oplus y < 2^{b}$, либо единица, и тогда $y \oplus z < 2^{b}$. В обоих случаях какая-то из более тесных пар строго лучше крайней — значит пару, между членами которой лежит третье число, можно не проверять.
Отсортируем: 3, 7, 13, 18, 25, 29, 38, 44, 52, 60 — и проверим только девять соседних пар вместо сорока пяти. Их XOR равны 4, 10, 31, 11, 4, 59, 10, 24, 8; наименьшее значение 4 достигается дважды: $3 \oplus 7 = 4$ и $25 \oplus 29 = 4$. Ответ сошёлся с перебором, и это независимая проверка, а не пересчёт того же самого.
Идея «старший разряд важнее всех младших вместе» — универсальная для битовых задач. Она превращает переборную задачу в жадный спуск по дереву, то есть в то же деление пополам, что и бинарный поиск, только режется не отрезок чисел, а множество кандидатов по очередному биту.
На YMLS такое вряд ли придёт в полном объёме, но сам приём «работать с числами поразрядно, от старших к младшим» вполне может понадобиться.
For the given data, the answer is 4, attained by 7 and 3: $7 \oplus 3 = 0111_2 \oplus 0011_2 = 0100_2 = 4$.
from itertools import combinations print(min(x ^ y for x, y in combinations(G, 2))) # 4
Pair enumeration takes $O(n^2)$ time and involves only 45 pairs here. It is too slow under olympiad constraints ($n$ up to $2\cdot10^5$, values below $2^{30}$), so a different approach is required.
The appropriate solution is a binary prefix tree, or binary trie.
Store the binary representations of the numbers in a tree as strings of length $K=30$, from the most significant bit to the least significant. When a new number $X$ arrives, perform two operations:
- Find a number $Y$ in the trie minimizing its XOR with $X$. Descend from the root. At each depth, first try the branch with the same bit as $X$, which contributes zero at this position. If that branch does not exist, take the only available branch.
- Insert $X$ into the trie.
Maintain the answer as the minimum over all insertions.
Why the greedy descent is correct. Suppose both branches are available at depth $d$. Matching the bit contributes zero at this position, while differing contributes one, with value $2^{K-d}$. One more significant bit outweighs all less significant bits combined, as established in the Bridge section. Therefore matching the more significant bit is preferable to any possible gain below it, and the greedy choice is optimal.
The time and space complexity are $O(NK)$, where $K$ is the number of bits.
The rule from the Triggers section applies: the minimum XOR is always attained by two adjacent values in sorted order. Here is the proof. Let $x<y<z$, and let $b$ be the most significant bit at which $x$ and $z$ differ. At this bit, $x$ has zero and $z$ has one, so $x\oplus z \ge 2^b$. All bits above $b$ coincide in $x$ and $z$. Since $y$ lies between them, it agrees with both in those higher bits. At bit $b$, either $y$ has zero, giving $x\oplus y < 2^b$, or it has one, giving $y\oplus z < 2^b$. In either case, a closer pair is strictly better than the outer pair. Thus a pair with a third number between its members never needs to be checked.
Sort the values: 3, 7, 13, 18, 25, 29, 38, 44, 52, 60. Check only nine adjacent pairs rather than forty-five. Their XORs are 4, 10, 31, 11, 4, 59, 10, 24, 8. The minimum, 4, is attained twice: $3 \oplus 7 = 4$ and $25 \oplus 29 = 4$. This agrees with exhaustive search and is an independent check.
The principle “a more significant bit outweighs all less significant bits combined” is universal in bitwise problems. It turns an exhaustive search into a greedy tree descent: the same kind of halving as binary search, except that the candidate set is partitioned by the next bit rather than by a numeric interval.
A full-strength version is unlikely on YMLS, but the underlying technique of processing numbers bit by bit, from most significant to least significant, may well be useful.