Nesse texto vamos falar um pouco a respeito de uma estrutura de dados muito poderosa e muito utilizada na maratona: a Árvore de segmentos.
Comecemos falando a respeito de um problema: o Range Sum Query (RSQ)
Dado um vetor a, realizaremos Q queries, isto é, perguntas do tipo:
Qual é a soma dos elementos do vetor no intervalo de l à r?
Denotaremos essa operação rsq(l, r).
Na estratégia Naive, simplesmente realizaremos a soma entre os elementos do intervalo dado:
- Complexidade: O(n) por query.
Nesta estratégia, criaremos um vetor de soma acumulada e utilizaremos a subtração entre somas de prefixos para calcular a soma em um determinado intervalo.
O vetor de soma acumulada representa a soma até um certo índice i, isto é:
Para construirmos o vetor de soma acumulada, sabemos de duas igualdades:
Utilizando o vetor acc, podemos calcular a soma em um intervalo (l,r), denominada rsq(l,r), da seguinte forma:
Vamos definir um novo tipo de query possível: , isto é, atualizar/sobreescrever (realizar um update) o elemento k com o valor x.
Mas como isso afetou as estratégias citadas?
Com essa mudança, ambas as estratégias serão em geral:
-
Soma acumulada:
-
Estratégia naive:
Mas existe uma solução! As tais Árvores de Segmentos!
A árvore de segmentos é uma estrutura de dados que, como diz o nome, se organiza em segmentos. Cada nó dessa árvore contém informação de um intervalo/segmento .
Para o problema dado (RSQ), essa informação é a soma dos elementos do intervalo, mas é importante notar que a Segment Tree é uma estrutura muito poderosa que pode armazenar outras informações, como por exemplo o elemento máximo/mínimo naquele intervalo, e pode resolver uma variedade enorme de problemas de Programação Competitiva.