Skip to content

Complexity & Constraints

In one sentence

Read the limits before you think about a solution: the size of \(N\) tells you how fast the algorithm must be, and a computer does roughly \(10^8\) simple steps per second.

1. What problem does it solve?

Example — 1927C · Choose the Different Ones! (2-custom_sorting · C, rating 1000)

You get an array \(a\) of length \(n\), an array \(b\) of length \(m\), and an even \(k\). Choose exactly \(k/2\) elements from \(a\) and exactly \(k/2\) from \(b\) so that the chosen ones contain every number \(1, 2, \dots, k\). Print YES or NO.

Limits: \(t \le 10^4\); \(n, m \le 2 \cdot 10^5\); \(k \le 2 \min(n, m)\); \(a_i, b_j \le 10^6\); the sums of \(n\) and of \(m\) over all tests are at most \(4\cdot10^5\).

Input                Output
6
6 5 6
2 3 8 5 6 5
1 3 4 10 5           YES
6 5 6
2 3 4 5 6 5
1 3 8 10 3           NO
3 3 4
1 3 5
2 4 6                YES
2 5 4
1 4
7 3 4 4 2            YES
1 4 2
2
6 4 4 2              NO
1 5 2
3
2 2 1 4 3            NO

Two ways to read the limits.

  • Looking only at one test: \(t = 10^4\) tests, each with \(n = 2\cdot10^5\), would be \(2 \cdot 10^9\) numbers. Nothing could even read that in time.
  • Looking at the sum constraint: all tests together have at most \(4\cdot10^5\) numbers. So an \(O(n + m + k)\) solution per test is \(O(8 \cdot 10^5)\) for the whole input.

The idea for this problem is simple once we are sure \(O(n + m + k)\) per test is allowed. For each value \(v \le k\) record whether it is in \(a\) and whether it is in \(b\):

  • only in \(a\): must come from \(a\); only in \(b\): must come from \(b\); in neither: impossible.
  • Answer YES iff no value is missing, \(\#\text{only } a \le k/2\) and \(\#\text{only } b \le k/2\) (values in both can fill whichever side is short).

2. The math

2.1 What Big-O measures

\(O(f(N))\) means "the number of steps grows at most like \(f(N)\) once \(N\) is large", ignoring constant factors. Doubling \(N\) doubles an \(O(N)\) loop, quadruples an \(O(N^2)\) one, and adds just one step to an \(O(\log N)\) one.

\(N\) \(\log_2 N\) \(N \log_2 N\) \(N^2\) \(2^N\)
\(10\) \(3.3\) \(33\) \(100\) \(1024\)
\(20\) \(4.3\) \(86\) \(400\) \(10^6\)
\(10^3\) \(10\) \(10^4\) \(10^6\)
\(10^5\) \(17\) \(1.7\cdot10^6\) \(10^{10}\)
\(2\cdot10^5\) \(18\) \(3.5\cdot10^6\) \(4\cdot10^{10}\)

2.2 From limits to algorithm

With about \(10^8\) simple steps per second, find the largest complexity whose value at the maximum \(N\) stays under the budget. For \(N = 2\cdot10^5\) the table above rules out \(N^2\) and allows \(N \log N\).

2.3 Counting steps for the example

Per test: read \(a\) (\(n\) steps), read \(b\) (\(m\)), fill two flag arrays of size \(k+1\), then scan \(1..k\). Total \(O(n + m + k)\), and since \(k \le 2\min(n,m)\) this is \(O(n + m)\). Summed over all tests: \(O(4\cdot10^5 + 4\cdot10^5)\). A fresh vector<int>(k + 1) in every test is fine for the same reason.

The trap: allocating an array of size \(10^6\) (the largest \(a_i\)) inside every test costs \(10^4 \cdot 10^6 = 10^{10}\) steps, even though each test is small. Size per-test arrays by the test, not by the global maximum.

3. Notes from our lessons

From the 8 February recap:

We will dive deeper into Time Complexity in the next class. $$ O(1) < O(\log n) < O(\sqrt{n}) < O(n) < O(n \log n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n) $$

From 18 March:

Time complexity order: $$ \log N < \sqrt{N} < N < N \log N < N^2 < N^3 < N^k < 2^N < \cdots $$

Rough rule of thumb for a 1s time limit:

Time Complexity Approximate Maximum N
\(O(\log N)\) \(10^{18}\) or larger
\(O(\sqrt{N})\) around \(10^{14}\)
\(O(N)\) around \(10^8\)
\(O(N \log N)\) around \(10^6\)
\(O(N^2)\) around \(10^4\)
\(O(N^3)\) around \(500\)
\(O(2^N)\) around \(20\) to \(25\)

These are only rough estimates, but they are very useful when choosing an approach during a contest.

From 22 March (Sum Constraints):

When a problem has multiple test cases, the limits on one test case are not always the full story.

For example:

  • \(T\) may be large.
  • Each test case may also have large \(N\) or \(Q\).
  • But the statement may guarantee that \(\sum N \le C\) or \(\sum Q \le C\) over all test cases.

This means the total amount of work is still bounded, even if one single test case looks large. So when analyzing time complexity, always check whether the problem gives a sum constraint.

4. Worked solution — Choose the Different Ones!

#include<bits/stdc++.h>

using namespace std;

using ll = long long;

void solve() {
    int n, m, k;
    cin >> n >> m >> k;

    // ina[v] / inb[v]: does v (1 <= v <= k) appear in a / in b
    vector<int> ina(k + 1, 0), inb(k + 1, 0);
    for (int i = 0; i < n; i++) {
        int x;
        cin >> x;
        if (x <= k) {
            ina[x] = 1;
        }
    }
    for (int i = 0; i < m; i++) {
        int x;
        cin >> x;
        if (x <= k) {
            inb[x] = 1;
        }
    }

    int onlya = 0, onlyb = 0;
    for (int v = 1; v <= k; v++) {
        if (!ina[v] && !inb[v]) {
            cout << "NO\n";
            return;
        }
        if (ina[v] && !inb[v]) {
            onlya++;
        }
        if (!ina[v] && inb[v]) {
            onlyb++;
        }
    }

    if (onlya <= k / 2 && onlyb <= k / 2) {
        cout << "YES\n";
    } else {
        cout << "NO\n";
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int T = 1;
    cin >> T;
    for (int i = 0; i < T; i++) {
        solve();
    }
    return 0;
}

Why the last check is enough: the \(k\) values split into only a, only b and both. Take all only a values from \(a\) (\(\le k/2\) of them) and all only b values from \(b\); the both values can go to whichever side still has room, and the two sides have exactly \(k/2 + k/2 = k\) slots in total.

5. Reading limits: a checklist

  1. Find the largest \(N\) (and \(Q\), and the value range).
  2. Look for "the sum of \(N\) over all test cases does not exceed …".
  3. Pick the complexity from the table in §3; if \(N \le 20\), think about bitmask brute force.
  4. Check the largest values too: do sums or products need long long? See Integer Types & Overflow.
  5. Size arrays per test by that test's \(N\), not by the global maximum.

6. Common mistakes

Resetting a huge global array in every test

fill(cnt.begin(), cnt.end(), 0) on a size-\(10^6\) array in each of \(10^4\) tests is \(10^{10}\) steps. Reset only what you touched, or allocate per test.

Ignoring the subtask limits

In AIO, the subtask limits tell you which slower solutions still score. AIO 2026 · Discount Destinations gives points to \(O(NK)\) before asking for \(O(N)\).

endl in a loop with \(10^5\) lines

endl flushes the output every time. Print "\n" instead.

7. Practice

Problem Set Rating What the limits say
1927C · Choose the Different Ones! 2-custom_sorting · C 1000 sum constraint allows \(O(n+m)\) per test (this page)
1851B · Parity Sort 2-custom_sorting · B 800 \(O(n \log n)\) with sum of \(n \le 2\cdot10^5\)
1097B · Petr and a Combination Lock 4-quick_power · C 1200 \(n \le 15\): try all \(2^{15}\) choices
1873F · Money Trees 5-BinarySearch · I 1300 \(O(n^2)\) is too slow, \(O(n)\) or \(O(n \log n)\)

Credits & licenses
  • The three quoted notes in §3 are from our lessons on 8 February, 18 March and 22 March, unchanged.
  • Example, growth table, step counting, worked solution and checklist are ours.