Feito por Thiago Mota
Imagine o seguinte problema, dado um vetor de elementos e
intervalos
queremos saber para cada uma das
perguntas a soma dos elementos da posição
até
no vetor.
A solução mais fácil seria andar pelo vetor de até
para cada uma das perguntas:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Ideias 06 - Soma de Prefixos | |
// Thiago Mota | |
#include <bits/stdc++.h> | |
using namespace std; | |
const int maxn = 100010; | |
int n, q, v[maxn]; | |
int main() { | |
cin >> n >> q; | |
for(int i = 1; i <= n; i++) { | |
cin >> v[i]; // Lendo o vetor | |
} | |
for(int i = 1; i <= q; i++) { | |
int l, r; | |
cin >> l >> r; | |
int soma = 0; | |
for(int j = l; j <= r; j++) | |
soma += v[j]; // Somando cada elemento de [l, r] | |
cout << soma << "\n"; | |
} | |
return 0; | |
} |
Sendo que isso fica em uma complexidade de , que para valores de
receberia um TLE.
A solução rápida seria utilizando soma de prefixos, vamos olhar para o seguinte vetor: , para resolver o problema da soma iremos definir um vetor de prefixo
de forma que
vai guardar a soma de todos os elementos em
de
até
, no caso desse vetor o prefixo ficaria assim:
, com esse vetor de prefixo podemos responder qualquer pergunta em um intervalo de
, mas caso olharmos para a soma da posição
podemos imaginar como sendo a soma de
menos a soma de
, ou seja, utilizando o vetor de prefixo podemos calcular a soma para qualquer intervalo
, segue um exemplo:
(
)
(
)
(
)
Resumindo, para calcular a soma de podemos calcular a soma de
e subtrair da soma de
, e para calcular essa soma podemos fazer
, segue o código:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Ideias 06 - Soma de Prefixos | |
// Thiago Mota | |
#include <bits/stdc++.h> | |
using namespace std; | |
const int maxn = 100010; | |
int n, q, v[maxn], pref[maxn]; | |
int main() { | |
cin >> n >> q; | |
for(int i = 1; i <= n; i++) { | |
cin >> v[i]; // Lendo o vetor | |
} | |
pref[1] = v[1]; // Prefixo da posição 1 é ele mesmo | |
for(int i = 2; i <= n; i++) { | |
pref[i] = pref[i-1] + v[i]; // O prefixo de i é o prefixo de i-1 adicionado do elemento na posição i | |
} | |
for(int i = 1; i <= q; i++) { | |
int l, r; | |
cin >> l >> r; | |
if(l == 1) { | |
cout << pref[r] << "\n"; // Se o l for 1, podemos apenas imprimir o prefixo. | |
}else { | |
cout << pref[r] - pref[l-1] << "\n"; // Senão, iremos imprimir a soma de [1, r] - [1, l-1] | |
} | |
} | |
return 0; | |
} |
A ideia de prefixo pode ser utilizada para multiplicação (utilizando divisão como operação oposta) ou qualquer outra operação que possua um inverso.
Exercícios para praticar:
OBI 2017 P1 - Segredo do Cofre