All IOI entries
Competitive Programming

IOI 2019 - Sequence (Line)

Given an array of n integers, find the minimum number of elements to change so the result is an arithmetic sequence a + bi for positions i = 0, 1,, n-1.

Source sync Apr 19, 2026
Track IOI
Year 2019
Files TeX and C++
Folder competitive_programming/ioi/2019/line
IOI2019TeXC++

Source-first archive entry

This page is built from the copied files in competitive_programming/ioi/2019/line. Edit competitive_programming/ioi/2019/line/solution.tex to update the written solution and competitive_programming/ioi/2019/line/solution.cpp to update the implementation.

The website does not replace those files with hand-maintained HTML. It reads the copied source tree during the build and exposes the exact files below.

Problem Statement

Rendered from the "Problem Summary" section inside solution.tex because this entry has no separate statement file.

Given an array of $n$ integers, find the minimum number of elements to change so the result is an arithmetic sequence $a + bi$ for positions $i = 0, 1, \ldots, n-1$.

Editorial

Rendered from the copied solution.tex file. The original TeX source remains available below.

Solution

Key Observation

If we keep elements at positions $i$ and $j$ ($i < j$), the common difference is $d = (\text{arr}[j] - \text{arr}[i]) / (j - i)$, which must be an integer. The starting value is $a = \text{arr}[i] - d \cdot i$.

Lemma.

If the optimal solution keeps $\ge 3$ elements, then at least two of the first three positions ($0, 1, 2$) are kept.

Proof.

If none of positions $0, 1, 2$ is kept, at most $n - 3$ elements are kept, which can only be optimal when $n \le 5$. If exactly one is kept, any single element can be paired with any other to define a candidate, but we need at least two kept elements to fix the arithmetic sequence. The lemma follows from a case analysis: among any three consecutive kept positions, at least one pair involves position $0$, $1$, or $2$.

Algorithm

  1. For each pair $(i, j)$ where $i \in \{0, 1, 2\}$ and $j > i$: compute $d$ and $a$, then count matches in $O(n)$.

  2. This gives $O(n)$ candidate sequences, each checked in $O(n)$ time.

  3. Handle edge cases: $n \le 2$ always has answer $0$.

Implementation

#include <bits/stdc++.h>
using namespace std;

int minimum_changes(vector<int>& arr) {
    int n = arr.size();
    if (n <= 2) return 0;

    int best = 2;  // can always keep at least 2 elements

    auto try_seq = [&](long long a, long long d) {
        int cnt = 0;
        for (int i = 0; i < n; i++)
            if ((long long)arr[i] == a + d * i) cnt++;
        best = max(best, cnt);
    };

    for (int i = 0; i < min(n, 3); i++) {
        for (int j = i + 1; j < n; j++) {
            long long diff = (long long)arr[j] - arr[i];
            long long gap = j - i;
            if (diff % gap != 0) continue;
            long long d = diff / gap;
            long long a = (long long)arr[i] - d * i;
            try_seq(a, d);
        }
    }

    return n - best;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<int> arr(n);
    for (int i = 0; i < n; i++) scanf("%d", &arr[i]);
    printf("%d\n", minimum_changes(arr));
    return 0;
}

Complexity Analysis

  • Time: $O(n^2)$ -- $O(n)$ candidate pairs, each checked in $O(n)$.

  • Space: $O(n)$.

Code

Exact copied C++ implementation from solution.cpp.

C++ competitive_programming/ioi/2019/line/solution.cpp

Exact copied implementation source.

Raw file
#include <bits/stdc++.h>
using namespace std;

int minimum_changes(vector<int>& arr) {
    int n = arr.size();
    if (n <= 2) return 0;

    int best = 2; // We can always keep at least 2 elements (or 1)

    // Try all pairs involving positions 0, 1, or 2
    // If the optimal keeps >= 3 elements, at least 2 must be among {0, 1, 2}.
    // Actually, at least one of the first 3 positions must be kept.
    // More precisely: if we keep elements at positions p1 < p2 < p3 < ...,
    // and p1 >= 3, then we only keep n-3 or fewer from positions 3..n-1,
    // so kept <= n-3. If n-3 > best so far, we'd need to try.
    // The standard approach: try pairs from first 3 positions with all others.

    auto try_seq = [&](long long a, long long d) {
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if ((long long)arr[i] == a + (long long)d * i)
                cnt++;
        }
        best = max(best, cnt);
    };

    for (int i = 0; i < min(n, 3); i++) {
        for (int j = i + 1; j < n; j++) {
            long long diff = (long long)arr[j] - arr[i];
            long long gap = j - i;
            if (diff % gap != 0) continue;
            long long d = diff / gap;
            long long a = (long long)arr[i] - d * i;
            try_seq(a, d);
        }
    }

    // Also try keeping just one element with various d values:
    // For n <= small, we could try all pairs. For large n, the above covers it.

    return n - best;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<int> arr(n);
    for (int i = 0; i < n; i++)
        scanf("%d", &arr[i]);
    printf("%d\n", minimum_changes(arr));
    return 0;
}

Source Files

Exact copied source-of-truth files. Edit solution.tex for the write-up and solution.cpp for the implementation.

TeX write-up competitive_programming/ioi/2019/line/solution.tex

Exact copied write-up source.

Raw file
\documentclass[11pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{amsmath,amssymb,amsthm}
\usepackage{listings}
\usepackage{geometry}
\usepackage{hyperref}
\geometry{margin=2.5cm}

\newtheorem{lemma}{Lemma}

\lstset{
  language=C++,
  basicstyle=\ttfamily\small,
  keywordstyle=\bfseries,
  breaklines=true,
  numbers=left,
  numberstyle=\tiny,
  frame=single,
  tabsize=2
}

\title{IOI 2019 -- Sequence (Line)}
\author{Solution}
\date{}

\begin{document}
\maketitle

\section{Problem Summary}
Given an array of $n$ integers, find the minimum number of elements to change so the result is an arithmetic sequence $a + bi$ for positions $i = 0, 1, \ldots, n-1$.

\section{Solution}

\subsection{Key Observation}
If we keep elements at positions $i$ and $j$ ($i < j$), the common difference is $d = (\text{arr}[j] - \text{arr}[i]) / (j - i)$, which must be an integer. The starting value is $a = \text{arr}[i] - d \cdot i$.

\begin{lemma}
If the optimal solution keeps $\ge 3$ elements, then at least two of the first three positions ($0, 1, 2$) are kept.
\end{lemma}
\begin{proof}
If none of positions $0, 1, 2$ is kept, at most $n - 3$ elements are kept, which can only be optimal when $n \le 5$. If exactly one is kept, any single element can be paired with any other to define a candidate, but we need at least two kept elements to fix the arithmetic sequence. The lemma follows from a case analysis: among any three consecutive kept positions, at least one pair involves position $0$, $1$, or $2$.
\end{proof}

\subsection{Algorithm}
\begin{enumerate}
  \item For each pair $(i, j)$ where $i \in \{0, 1, 2\}$ and $j > i$: compute $d$ and $a$, then count matches in $O(n)$.
  \item This gives $O(n)$ candidate sequences, each checked in $O(n)$ time.
  \item Handle edge cases: $n \le 2$ always has answer $0$.
\end{enumerate}

\section{Implementation}

\begin{lstlisting}
#include <bits/stdc++.h>
using namespace std;

int minimum_changes(vector<int>& arr) {
    int n = arr.size();
    if (n <= 2) return 0;

    int best = 2;  // can always keep at least 2 elements

    auto try_seq = [&](long long a, long long d) {
        int cnt = 0;
        for (int i = 0; i < n; i++)
            if ((long long)arr[i] == a + d * i) cnt++;
        best = max(best, cnt);
    };

    for (int i = 0; i < min(n, 3); i++) {
        for (int j = i + 1; j < n; j++) {
            long long diff = (long long)arr[j] - arr[i];
            long long gap = j - i;
            if (diff % gap != 0) continue;
            long long d = diff / gap;
            long long a = (long long)arr[i] - d * i;
            try_seq(a, d);
        }
    }

    return n - best;
}

int main() {
    int n;
    scanf("%d", &n);
    vector<int> arr(n);
    for (int i = 0; i < n; i++) scanf("%d", &arr[i]);
    printf("%d\n", minimum_changes(arr));
    return 0;
}
\end{lstlisting}

\section{Complexity Analysis}
\begin{itemize}
  \item \textbf{Time}: $O(n^2)$ -- $O(n)$ candidate pairs, each checked in $O(n)$.
  \item \textbf{Space}: $O(n)$.
\end{itemize}

\end{document}