De ce contează?
Algoritmul tău e perfect, dar citești datele în ordinea greșită sau scrii rezultatul într-un format nepotrivit — și tot primești 0. Formatul datelor contează la fel de mult ca logica. Înainte să scrii o linie de cod, citește enunțul de două ori și înțelege exact cum arată problema.in.
Structura tipică a unui fișier .in
Enunțurile românești folosesc câteva formate standard. Recunoaște-le din prima și știi imediat cum să citești.
Format 1 — n urmat de n valori:
5
3 7 1 9 2int n; fin >> n;
for (int i = 0; i < n; i++) { fin >> v[i]; }Format 2 — n și m pe prima linie, matrice pe liniile următoare:
3 4
1 2 3 4
5 6 7 8
9 0 1 2int n, m; fin >> n >> m;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
fin >> a[i][j];Format 3 — perechi de valori până la EOF:
1 5
3 8
2 7int a, b;
while (fin >> a >> b) {
// proceseaza perechea
}Format 4 — o singură valoare pe linie:
42
17
93int x;
while (fin >> x) { ... }Șablonul complet de concurs
Acesta e punctul de plecare pe care îl poți folosi la orice problemă OJI/ONI:
#include <iostream>
#include <fstream>
using namespace std;
ifstream fin("problema.in");
ofstream fout("problema.out");
int main() {
int n;
fin >> n;
// ... rezolva problema ...
fout << rezultat << "\n";
return 0;
}Declararea fin și fout global (în afara lui main) e o practică comună la concurs — le poți folosi din orice funcție fără să le transmiți ca parametri. Nu e obligatoriu, dar simplifică codul când ai mai multe funcții.
ios::sync_with_stdio — citire mai rapidă
Pentru probleme cu foarte multe date (n = 10⁶ sau mai mult), adaugă la începutul lui main:
ios::sync_with_stdio(false);
cin.tie(nullptr);Dezactivează sincronizarea cu scanf/printf și accelerează cin/cout de ~5–10×. Nu combina cu scanf/printf după ce activezi acest trick — comportamentul devine nedefinit.
Greșeli de format frecvente
Un spațiu în plus la finalul liniei poate face diferența dintre AC și WA pe unii graderi:
// GRESIT: spatiu in plus dupa ultimul element
fout << a << " " << b << " " << c << "\n"; // "1 2 3 "
// CORECT: spatiu doar intre elemente
for (int i = 0; i < n; i++) {
if (i > 0) fout << " ";
fout << v[i];
}
fout << "\n";Greșeala 1: Amesteci fin >> cu getline(fin, ...). După fin >> n, cursorul rămâne chiar înainte de \n. Primul getline citește acel newline gol. Adaugă fin.ignore() între ele pentru a-l consuma.
Greșeala 2: Folosești while (!fin.eof()) în loc de while (fin >> x). Varianta cu eof() poate executa o iterație în plus cu date nedefinite după ultimul element valid.
Greșeala 3: Indecși inconsistenți: declari int v[n] indexat 0..n-1, dar citești cu for (i=1; i<=n; i++). Sau invers. Alege o convenție (0-based sau 1-based) și aplică-o uniform în tot programul.
Greșeala 4: Scrii endl în loc de "\n" în bucle mari. endl golește bufferul la fiecare apel — de 50–100× mai lent decât "\n" pentru output voluminos.