Aula por Arthur Lobo
Nesta aula, abordaremos uma técnica eficiente para contar a quantidade de inversões em um array usando a estrutura de dados Binary Indexed Tree (BIT).
Conhecimento prévio necessário:
O que é uma inversão?
Dado um Array com elementos
, dizemos que
e
estão invertidos (são uma inversão) se
e
, ou seja, eles estão fora de ordem um em relação ao outro. Formalmente, o par
é uma inversão
e
.
A quantidade de inversões é a quantidade de pares que são uma inversão. Por exemplo, no array
existem duas inversões:
e
.
Comprimindo o Array
Note que a o real valor em cada posição no array não importa, só importa a os valores de cada posição em relação aos outros valores presentes no array. Por exemplo, os arrays
e
são equivalentes em relação as inversões.
Por conta disso, vamos querer fazer com que os valores no array inicial sejam os menores possíveis, deixando todos eles no intervalo . Os dois arrays citados a cima virariam
, em que todos os valores estão de
até
(
).
Para fazer isso, basta utilizarmos a técnica de compreensão de coordenadadas no array inicial. Veja aqui a aula do NOIC sobre compressão de coordenadas: Link da Aula.
Contando as inversões
Vamos contar, para cada , quantos
(
) existem tal que
é uma inversão. Nosso objetivo será percorrer o array do final até o começo mantendo uma BIT em que a posição
guarda quantos elementos iguais a
já foram percorridos, então quando estivermos em
, basta contarmos quantos elementos
já foram percorridos fazendo uma query na BIT.
Desse jeito, quando estamos em vamos realizar os seguintes passos:
- Sabemos que já percorremos
e eles já foram somados na BIT.
- Para contar quantos
existem tal que
é uma inversão, fazemos uma query na BIT contando quantos elementos menores que
já foram somados na BIT e adicionamos isso na resposta: quantidade_de_inversões+=
.
- Agora adicionamos
na BIT, somando
na posição
:
.
- Agora podemos seguir para
, mas com os elementos
adicionados na BIT.
Por exemplo, no array , a query retornaria 0 nas posições
e
, mas retornaria
na posição
. Já no array
, a query retornaria
e
nas posições
e
, respectivamente.
Obs: Não esqueça de utilizar long long para contar as inversões!