Escrito por Lúcio Figueiredo
A técnica de somas de prefixo é uma das mais recorrentes em olimpíadas de informática. Neste material, vamos definir as somas de prefixo e apresentar algumas de suas aplicações.
Motivação Inicial
Imagine o seguinte problema: Nos é dado um vetor de tamanho e perguntas (ou queries). Cada query consiste de dois índices e . Para cada uma dessas queries, devemos imprimir como resposta a soma dos números de com indíces entre e ; ou seja, a resposta de cada query é a soma .
Para resolver o problema, podemos utilizar uma solução bem simples: basta que percorramos o vetor com um loop for indo desde o índice até o índice , armazenando a soma dos valores em uma variável de resposta. Porém, note que a complexidade desta solução é para cada query; logo, a complexidade total da solução é . Para valores de e indo até , a solução realizará operações, o que não é eficiente. Como podemos resolver o problema com uma complexidade melhor?
Somas de Prefixo
Um prefixo de um vetor é definido como um intervalo contínuo deste vetor que começa do seu primeiro índice. Em particular, o -ésimo prefixo do vetor é o intervalo contínuo de elementos . Já uma soma de prefixo de um vetor é simplesmente a soma dos elementos de um prefixo. Ou seja, a -ésima soma de prefixo do vetor , denominada por , é igual à soma .
Na imagem acima, podemos observar um exemplo de vetor e cada uma de suas somas de prefixo. Para calcular as somas de prefixo de um vetor , podemos usar o seguinte simples algoritmo, com complexidade :
- Inicialmente, fazemos ;
- Em seguida, iteramos por cada índice do vetor em sequência;
- Para calcular , basta fazer . Ou seja, a soma dos primeiros valores de é igual à soma dos primeiros valores somada ao valor do -ésimo elemento.
Somas de intervalos em
Mas como somas de prefixo nos ajudam a encontrar a soma de um intervalo qualquer? Observe que, utilizando somas de prefixo, conseguimos encontrar a soma do intervalo - este valor é exatamente a soma . Porém, esta soma inclui mais elementos do vetor do que o desejado; especificamente, a soma de prefixo soma todos os elementos no intervalo e, também, todos os elementos em . Portanto, temos a seguinte relação:
Porém, note que é exatamente igual a ! Logo, temos que
Ou seja, a soma do intervalo é igual ao valor . A imagem abaixo ilustra este fato de maneira intuitiva:
Portanto, utilizando somas de prefixos, conseguimos calcular somas de intervalos quaisquer de um vetor com complexidade : basta imprimir o valor .
O código a seguir implementa a solução para o problema original indicada acima, utilizando somas de prefixos:
Problemas para praticar:
A lista a seguir contém alguns problemas que utilizam as ideias exploaradas na aula. Bons treinos!