ICPC 2024
ICPC 2024

C. Citizenship

It has been a long time since you moved to a different country and you have decided it is time to become a citizen. Your new country has a strict residency requirement for all applicants. To apply, you must have been physically present in the country for at...

Updated May 21, 2026
Track ICPC
Year 2024
Statement Text + PDF
TeXC++Statement textStatement PDF

Problem Statement

Formatted from the contest statement text, with sample tests broken out into copyable blocks.

Time limit 4 seconds

It has been a long time since you moved to a different country and you have decided it is time to become a citizen. Your new country has a strict residency requirement for all applicants. To apply, you must have been physically present in the country for at least d days per year, for the past y consecutive years. These years are counted in 12-month periods backwards from the application date. For this problem, assume that a calendar year has 12 months of 365 Image via Rawpixel, CC0 days, and each month has exactly the number of days below:

month    01    02    03   04    05   06    07    08   09     10   11   12
 days    31    28    31   30    31   30    31    31   30     31   30   31

For example, if you were to apply on 2024–09–19 you must have been in the country for at least d days during the 12-month periods from 2023–09–19 to 2024–09–18, 2022–09–19 to 2023–09–18, and so on for y such periods. You have lived in the country for at least y years, but having traveled a lot, you are not sure if you meet the residency requirement. Write a program that finds the earliest date you can submit your citizenship application given your travel history.

Input

The first line contains three integers n, y and d (1 ≤ n ≤ 500, 1 ≤ y ≤ 1 000, 1 ≤ d ≤ 365). You have been out of the country n times and y and d specify the country’s residency requirement as described above. Each of the following n lines contains two dates in the form YYYY-MM-DD (0000 ≤ YYYY ≤ 5 000, 01 ≤ MM ≤ 12, 01 ≤ DD ≤ 31). You have been out of the country between the two dates, inclusive. All dates in the input are sorted in increasing order. The only dates which may be equal are dates on the same line. All given dates are valid.

Output

Output the earliest date on which you meet the residency requirement. The date must be after the last date of the input.

Sample Tests

Sample 1
Sample Input
 3 5 240
 2022-02-28 2022-10-01
 2022-11-11 2022-11-11
 2023-12-30 2024-01-01
Sample Output
2024-05-31
Sample 2
Sample Input
3 5 240
2011-11-11 2012-12-12
2022-02-28 2022-10-01
2025-01-01 2025-06-30
Sample Output
2028-02-26

Editorial

The solution write-up is rendered from the LaTeX source, with equations kept live through MathJax.

Key Observations

  • The only thing that matters about a date is its position modulo $365$. For a fixed residue $r = A \bmod 365$, the relevant 12-month periods are aligned to a fixed partition of the timeline into blocks of length $365$.

  • Therefore there are only $365$ possible alignments to check.

  • For one fixed residue $r$, define block $b$ as \[ [r + 365b,\; r + 365b + 364]. \] The application date $A = r + 365t$ is valid exactly when blocks $t-y, t-y+1, \dots, t-1$ are all good, where a block is good if it contains at most $365-d$ absent days.

  • The absence intervals are few, but the total date range is still small enough: at most about $5000 \cdot 365 + 1001 \cdot 365$. A plain prefix-sum over days is easily fast enough.

Algorithm

  1. Convert every calendar date to an integer day number using the fixed 365-day calendar.

  2. Mark all absent days with a difference array and build a prefix sum of absent days.

  3. Let $L$ be the last day in the input. It is enough to search up to $L + 365(y+1)$, because after that all $y$ required years lie completely after the last trip and are therefore automatically valid.

  4. For each residue $r \in \{0,\dots,364\}$:

    1. Scan the 365-day blocks with that alignment.

    2. For each block, compute its absent-day count in $O(1)$ from the prefix sum and decide whether the block is good.

    3. Maintain the current run length of consecutive good blocks.

    4. As soon as the run length reaches $y$, the application date immediately after the last block in that run is valid. If it is after $L$, update the global minimum answer.

    5. Convert the minimum day number back to YYYY-MM-DD.

    Correctness Proof

    We prove that the algorithm outputs the earliest valid application date.

    Lemma 1.

    For a fixed residue $r$, an application date $A \equiv r \pmod{365}$ is valid if and only if the $y$ consecutive 365-day blocks immediately before $A$ in the $r$-aligned partition are all good.

    Proof.

    Write $A = r + 365t$. Then \[ [A-365, A-1] = [r + 365(t-1),\; r + 365t - 1], \] which is exactly block $t-1$. Similarly, the next earlier year is block $t-2$, and so on down to block $t-y$. So the $y$ periods required by the statement are exactly the $y$ consecutive blocks immediately before $A$. Each period is valid exactly when its absent-day count is at most $365-d$. □

    Lemma 2.

    For a fixed residue $r$, when the scan first finds a run of at least $y$ consecutive good blocks ending at block $b$, the date $A = r + 365(b+1)$ is the earliest valid application date with residue $r$.

    Proof.

    By Lemma 1, $A$ is valid because the preceding $y$ blocks are good. Any earlier date with the same residue has the form $r + 365t$ with $t \le b$. Its preceding $y$ blocks must therefore end at some block strictly before $b$. Since $b$ is the first point where the scan sees $y$ consecutive good blocks, no such earlier date can be valid. □

    Lemma 3.

    There exists a valid application date no later than $L + 365(y+1)$, where $L$ is the last day in the input.

    Proof.

    Consider any date $A > L + 365y + 364$. Then the earliest of the $y$ required periods starts at $A - 365y > L$. So all $y$ required 365-day periods lie completely after the last recorded trip and contain zero absent days. Hence they are all valid. □

    Theorem.

    The algorithm outputs the earliest valid application date after the last input date.

    Proof.

    By Lemma 3, the search range always contains at least one valid date. For each residue class, Lemma 2 gives the earliest valid date with that residue. Taking the minimum over all 365 residues therefore yields the earliest valid date overall. □

    Complexity Analysis

    Let $T$ be the number of days scanned. Here \[ T = O(5000 \cdot 365 + y \cdot 365), \] which is at most about $2.2 \cdot 10^6$.

    Building the difference array and prefix sums takes $O(T + n)$. The 365 residue scans together also process only $O(T)$ blocks. Thus the total running time is $O(T + n)$ and the memory usage is $O(T)$.

    Implementation Notes

    • Since the calendar is fixed and has no leap years, date conversion is just base-365 arithmetic with the given month lengths.

    • The output must be after the last date in the input, so the candidate date must satisfy $A > L$.

    • Difference arrays handle inclusive absence intervals cleanly: add $+1$ at the start day and $-1$ at the day after the end.

Code

C++ solution used for this page.

C++

Clean code view with a raw-file link when you want the original source.

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

namespace {

constexpr int MONTHS = 12;
constexpr int YEAR_DAYS = 365;
const int MONTH_LEN[MONTHS] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int day_of_year(int month, int day) {
    int ans = 0;
    for (int i = 0; i < month - 1; ++i) {
        ans += MONTH_LEN[i];
    }
    return ans + day - 1;
}

int parse_date(const string& s) {
    const int year = stoi(s.substr(0, 4));
    const int month = stoi(s.substr(5, 2));
    const int day = stoi(s.substr(8, 2));
    return year * YEAR_DAYS + day_of_year(month, day);
}

string format_date(int serial) {
    const int year = serial / YEAR_DAYS;
    int rem = serial % YEAR_DAYS;
    int month = 1;
    while (rem >= MONTH_LEN[month - 1]) {
        rem -= MONTH_LEN[month - 1];
        ++month;
    }
    const int day = rem + 1;

    ostringstream out;
    out << setw(4) << setfill('0') << year << '-'
        << setw(2) << setfill('0') << month << '-'
        << setw(2) << setfill('0') << day;
    return out.str();
}

void solve() {
    int n, y, d;
    cin >> n >> y >> d;
    const int max_absent = YEAR_DAYS - d;
    const int history_shift = YEAR_DAYS * y;

    vector<pair<int, int>> trips(n);
    int last_day = 0;
    for (int i = 0; i < n; ++i) {
        string l, r;
        cin >> l >> r;
        trips[i] = {parse_date(l) + history_shift, parse_date(r) + history_shift};
        last_day = max(last_day, trips[i].second);
    }

    const int limit = last_day + YEAR_DAYS * (y + 1);
    vector<int> diff(limit + 2, 0);
    for (const auto& trip : trips) {
        ++diff[trip.first];
        --diff[trip.second + 1];
    }

    vector<int> absent(limit + 1, 0);
    vector<int> pref(limit + 2, 0);
    int cur = 0;
    for (int day = 0; day <= limit; ++day) {
        cur += diff[day];
        absent[day] = (cur > 0 ? 1 : 0);
        pref[day + 1] = pref[day] + absent[day];
    }

    int answer = limit;
    for (int residue = 0; residue < YEAR_DAYS; ++residue) {
        int run = 0;
        for (int block = 0; residue + block * YEAR_DAYS + YEAR_DAYS - 1 <= limit; ++block) {
            const int start = residue + block * YEAR_DAYS;
            const int finish = start + YEAR_DAYS - 1;
            const int days_absent = pref[finish + 1] - pref[start];
            if (days_absent <= max_absent) {
                ++run;
            } else {
                run = 0;
            }

            if (run >= y) {
                const int apply_day = residue + (block + 1) * YEAR_DAYS;
                if (apply_day > last_day) {
                    answer = min(answer, apply_day);
                    break;
                }
            }
        }
    }

    cout << format_date(answer - history_shift) << '\n';
}

}  // namespace

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

    solve();
    return 0;
}

Source Files and Assets

Raw files are still available here when you want the original TeX, C++, or statement assets.

Show raw files