Salah satu jebakan terbesar bagi pemula CP adalah bukan algoritma, tetapi parsing input dan format output. Soal CP sering menggunakan format spesifik — “baca t, kemudian untuk setiap test case baca n lalu n elemen” — dan kesalahan kecil seperti lupa newline atau salah tipe data (int vs long long) menyebabkan Wrong Answer yang sulit dilacak. Pada Chapter ini kita akan memetakan tiga pola I/O paling umum di CP, menjelaskan format output standar, dan menulis template siap pakai untuk setiap pola. Tujuan akhirnya: ketika membaca soal baru, kita langsung tahu struktur I/O tanpa perlu eksperimen.

Tiga Pola Input Utama #

PolaFormat InputKapan Muncul
Single test casen lalu n elemenSoal klasik (sum, max, sort)
Multiple test caset lalu t blok, tiap blok punya n elemenCodeforces standar
Edge list / matrixn m lalu m baris pasangan u v, atau n baris m kolomSoal graph, grid, matriks

Mekanisme: Cara Kerja std::cin #

std::cin >> x melakukan tiga hal:

  1. Skip whitespace — spasi, tab, newline, semuanya dilewati.
  2. Parse sesuai tipe — integer, float, string non-whitespace.
  3. Sisakan sisa input di buffer untuk pembacaan berikutnya.

Karena cin skip whitespace, kita dapat membaca “5\n3 9 2 7 5” dengan cin >> n; for (i=0;i<n;i++) cin >> a[i]; tanpa peduli apakah elemen dipisah spasi atau newline. Hal ini sangat nyaman tetapi juga berbahaya: kita mungkin tidak menyadari bahwa input sebenarnya terstruktur berbeda dari asumsi.

Kode: Tiga Pola I/O Siap Pakai #

cpp
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

// Pola 1: Single test case
// Input: n, kemudian n integer. Output: sum.
long long solve_sum(const std::vector<int>& a) {
    long long s = 0;
    for (int x : a) s += x;
    return s;
}

// Pola 2: Multiple test case
// Input: t, untuk setiap test: n, kemudian n integer.
// Output: untuk setiap test, sum dari n integer.
void solve_multiple() {
    int t;
    std::cin >> t;
    while (t--) {
        int n;
        std::cin >> n;
        std::vector<int> a(n);
        for (int i = 0; i < n; ++i) std::cin >> a[i];
        std::cout << solve_sum(a) << '\n';
    }
}

// Pola 3: Baca pasangan (u, v) — edge list
void solve_edges() {
    int n, m;
    std::cin >> n >> m;
    std::vector<std::pair<int,int>> edges(m);
    for (int i = 0; i < m; ++i) {
        std::cin >> edges[i].first >> edges[i].second;
    }
    std::cout << "n=" << n << " m=" << m << " edges:\n";
    for (auto& [u, v] : edges) {
        std::cout << "  " << u << " - " << v << '\n';
    }
}

int main() {
    // Demo Pola 1 dengan input internal
    std::vector<int> demo = {1, 2, 3, 4, 5};
    std::cout << "=== Pola 1: Single case ===\n";
    std::cout << "sum(";
    for (size_t i = 0; i < demo.size(); ++i) {
        std::cout << demo[i];
        if (i + 1 < demo.size()) std::cout << ',';
    }
    std::cout << ") = " << solve_sum(demo) << "\n\n";

    std::cout << "=== Pola 2: Multiple test case (simulasi) ===\n";
    std::cout << "Format input tipikal:\n";
    std::cout << "  t           (jumlah test case)\n";
    std::cout << "  n1          (jumlah elemen test 1)\n";
    std::cout << "  a1 a2 ... an1\n";
    std::cout << "  n2\n";
    std::cout << "  a1 a2 ... an2\n";
    std::cout << "  ...\n\n";
    std::cout << "Output:\n";
    std::cout << "  sum1\n";
    std::cout << "  sum2\n";
    std::cout << "  ...\n\n";

    std::cout << "=== Pola 3: Edge list (graph) ===\n";
    std::cout << "Format input tipikal:\n";
    std::cout << "  n m        (n node, m edge)\n";
    std::cout << "  u1 v1      (edge 1)\n";
    std::cout << "  u2 v2\n";
    std::cout << "  ...\n\n";

    std::cout << "=== Format Output Umum ===\n";
    std::cout << "Tipe                | Contoh\n";
    std::cout << "--------------------|-----------------------------------\n";
    std::cout << "Single integer      | 42\n";
    std::cout << "Multiple per baris  | 1 2 3 (dipisah spasi)\n";
    std::cout << "Array satu per baris| a[0]\\na[1]\\n...\n";
    std::cout << "YES/NO              | YES\n";
    std::cout << "Pair/tuple          | (1, 2)\n";
    std::cout << "Floating point      | 3.14159265358979 (sesuai presisi)\n";
    return 0;
}

Output yang Dihasilkan:

text
=== Pola 1: Single case ===
sum(1,2,3,4,5) = 15

=== Pola 2: Multiple test case (simulasi) ===
Format input tipikal:
  t           (jumlah test case)
  n1          (jumlah elemen test 1)
  a1 a2 ... an1
  n2
  a1 a2 ... an2
  ...

Output:
  sum1
  sum2
  ...

=== Pola 3: Edge list (graph) ===
Format input tipikal:
  n m        (n node, m edge)
  u1 v1      (edge 1)
  u2 v2
  ...

=== Format Output Umum ===
Tipe                | Contoh
--------------------|-----------------------------------
Single integer      | 42
Multiple per baris  | 1 2 3 (dipisah spasi)
Array satu per baris| a[0]\na[1]\n...
YES/NO              | YES
Pair/tuple          | (1, 2)
Floating point      | 3.14159265358979 (sesuai presisi)

Bedah Kode Baris-per-Baris #

  1. std::cin >> n;: baca integer pertama. cin otomatis skip whitespace sebelumnya.
  2. while (t--): pola idiomatik untuk “ulangi t kali”. t-- post-decrement — saat t = 0, kondisi false, loop berhenti.
  3. std::vector<int> a(n); for (int i = 0; i < n; ++i) std::cin >> a[i];: alokasi vektor berukuran n lalu baca elemen. Bisa juga pakai a.reserve(n) + push_back tetapi index assignment sedikit lebih cepat.
  4. std::vector<std::pair<int,int>> edges(m);: untuk edge list, vektor pasangan adalah struktur paling ringkas. first = u, second = v.
  5. for (auto& [u, v] : edges): structured binding C++17 — destrukturisasi pair ke variabel u dan v. Lebih readable dari edges[i].first.
  6. std::cout << " " << u << " - " << v << '\n';: cetak pasangan dengan format. Untuk output graph problem, format “u - v” atau “u v” tergantung soal.

Format Output Standar #

TipeFormatContoh
Single integerCetak nilai + newline42\n
Array spasiElemen dipisah spasi, newline akhir1 2 3 4 5\n
Array newlineSatu elemen per baris1\n2\n3\n4\n5\n
YES/NOKapital, newline akhirYES\n atau NO\n
Float presisisetprecision(n)3.14159265358979\n
Pair/tuple(a, b) atau a b(1, 2)\n

Untuk float dengan presisi tinggi:

cpp
#include <iomanip>
std::cout << std::fixed << std::setprecision(10) << ans << '\n';

Memilih Tipe Data dari Constraint #

Constraint NilaiTipe yang Aman
`a[i]
`a[i]
n ≤ 10^5, sum bisa besarlong long untuk akumulator
Hasil kombinasi a[i] * b[i]Cast ke long long sebelum *
0 ≤ a[i] ≤ 10^9 dan modulo 10^9+7long long untuk operasi antara

Ringkasan #

  • Tiga pola I/O utama: single test case, multiple test case (t di awal), edge list / matrix.
  • std::cin >> x otomatis skip whitespace — fleksibel tetapi perlu hati-hati dengan getline.
  • Format output bervariasi: integer tunggal, array spasi/newline, YES/NO, float presisi.
  • Pilih tipe data dari constraint: int untuk |v| ≤ 10^9, long long untuk sum atau |v| ≤ 10^18.
  • Selalu cetak newline di akhir output — beberapa judge ketat.
  • Uji dengan sample input sebelum submit untuk verifikasi format.