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