Solução Informática - Nível Iniciante - Semana 24

Escrito por Pedro Racchetti

Conhecimento prévio necessário:

A ideia para resolvermos esse problema, é perceber que se estamos analisando a soma do prefixo de i,  e já encontramos algum outro prefixo com valor igual a esse, então temos que adicionar um novo valor, já que entre esse outro prefixo e i, os números com certeza somam a 0. Como esse valor pode ser arbitrariamente grande, podemos adicionar um valor muito grande, tal que nenhum intervalo que passe por ele terá soma 0. Portanto, podemos passar a ignorar todos os prefixos até então, e recomeçar a soma dos prefixos. Para isso, precisamos apenas de uma variável, pref que guardará o prefixo atual, e um set para guarda todos os prefixos que estão sendo analisados.

Segue o código, comentado, para melhor compreensão do problema:


#include<bits/stdc++.h>
using namespace std;
typedef long long ll; //Os valores das somas podem passar de 2*10^9,
//então usaremos essa abreviação pra long long
const int MAXN = 2e5 + 10;
set<ll> s;
ll t[MAXN];
int main(){
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%lld", &t[i]);
//lemos os valores das transições
}
s.insert(0);
//iniciaremos o set com valor 0
//para não testarmos se o prefixo é igual a 0
//podendo então usar o algoritmo descrito normalmente
int ans = 0;
ll pref = 0;
for(int i = 1; i <= n; i++){
pref += t[i];
if(s.find(pref) != s.end()){
//se existe algum valor no set igual a soma atual,
//sabemos que existe um intervalo de soma 0
//portanto, inserimos uma nova transação e reiniciamos o set
ans++;
s.clear();
s.insert(0);
pref = t[i];
}
//adicionamos o prefixo atual
s.insert(pref);
}
printf("%d\n",ans );
}

view raw

extrato.cpp

hosted with ❤ by GitHub