CCC 2017 S1 Sum Game Solution: Running Prefix Sums and Last Equal Day



Start NorthStar

CP Weekly Challenge

CCC 2017 S1 Sum Game Solution: Running Prefix Sums and Last Equal Day

Learn how to solve Sum Game with running prefix sums, cumulative totals, and last-valid-position tracking in Python and C++.

CP Weekly Challenge

CCC 2017 S1 Sum Game 题解:用 Running Prefix Sum 找最后一次平局

用 running prefix sum 维护两队累计总分,找出最后一次累计平局日。

Share this article

Copy the link, open your phone share sheet, scan the QR code for WeChat, or send by email.




Email

This problem is about two baseball teams, but the algorithmic idea is a classic running prefix sum. We compare the two teams' cumulative scores after each day and remember the last day when those totals are equal.

The important detail is that we are not comparing the scores from a single day. We are comparing the total scores from day 1 through day K.

Where This Fits in the CCC DSA Map

  • Level: Senior S1
  • Pattern: Running Prefix Sum, Last Valid Position
  • Prerequisite: arrays/lists, loops, accumulation variables, indexing, careful output convention
  • What this teaches: You do not always need a full prefix array; when only the current cumulative state matters, rolling totals are enough.
  • Where it appears again: prefix sums, range sums, two-array comparisons, sweep-line style accumulation

What to Study Next

  • Related CP Weekly problems: CCC 2025 J4 Sunny Days for prefix/suffix consecutive counts, CCC 2021 S1 Crazy Fencing for array accumulation (coming soon), CCC 2020 S3 Searching for Strings for sliding window (coming soon).
  • Related Python / C++ foundations: loops and accumulation, lists/vectors, indexing, integer totals.
  • Related DSA roadmap article: CCC Prefix and Sliding Window Patterns (planned).

What the Problem Is Asking

The season lasts for N days. The Swifts and the Semaphores each play one game per day.

The input gives:

N
daily scores for the Swifts
daily scores for the Semaphores

We need to output the largest integer K such that after K days:

Swifts total score == Semaphores total score

If there is no such day after the season starts, we output 0.

The teams are tied before any games are played, but that does not count as a positive K.

Where Beginners Often Get Stuck

The first common mistake is comparing daily scores instead of cumulative scores. The problem asks whether the two teams have the same total after K days.

The second common mistake is stopping at the first equal total. The problem asks for the largest K, so we must scan all days and keep updating the answer.

The third common mistake is forgetting that the answer can be 0.

Core Algorithm Idea

Maintain two running totals:

swift_total
semaphore_total

For each day, add both teams' scores to their totals. If the totals are equal, record the current day as the answer.

Because we scan days from left to right, the last recorded equal day is automatically the largest valid K.

Python Solution

N = int(input())
swift_scores = list(map(int, input().split()))
semaphore_scores = list(map(int, input().split()))

swift_total = 0
semaphore_total = 0
answer = 0

for i in range(N):
    swift_total += swift_scores[i]
    semaphore_total += semaphore_scores[i]

    if swift_total == semaphore_total:
        answer = i + 1

print(answer)

C++ Solution

#include <iostream>
#include <vector>
using namespace std;

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

    int N;
    cin >> N;

    vector<int> swift(N);
    vector<int> semaphore(N);

    for (int i = 0; i < N; i++) {
        cin >> swift[i];
    }

    for (int i = 0; i < N; i++) {
        cin >> semaphore[i];
    }

    int swiftTotal = 0;
    int semaphoreTotal = 0;
    int answer = 0;

    for (int i = 0; i < N; i++) {
        swiftTotal += swift[i];
        semaphoreTotal += semaphore[i];

        if (swiftTotal == semaphoreTotal) {
            answer = i + 1;
        }
    }

    cout << answer << "\n";
    return 0;
}

Complexity Analysis

We scan the N days once.

The time complexity is:

O(N)

The shown implementation stores the two score arrays, so the memory complexity is:

O(N)

The idea can also be implemented with O(1) extra memory if the input is streamed or processed in a different format.

Common Mistakes

  1. Comparing daily scores instead of cumulative scores.
  2. Stopping at the first equal cumulative total.
  3. Forgetting that the answer can be 0.
  4. Using i instead of i + 1 for the day number.
  5. Mixing up prefix-array indices with day numbers.

Review Questions

  1. Why do we need cumulative totals in this problem?
  2. Why should we continue scanning after finding an equal day?
  3. Why is answer initialized to 0?
  4. Why does i + 1 represent the current day?
  5. When would a full prefix sum array be more useful than two running totals?

这道题表面上是棒球比分,实际上是在考一个很基础但非常重要的竞赛思维:边读数组,边维护累计值。

Sum Game 不要求我们输出每一天的累计比分,也不要求找所有平局日。它只问一件事:赛季开始后的第几天,两支队伍的累计得分最后一次相等?

本题在 CCC DSA 地图里的位置

  • Level: Senior S1
  • Pattern: Running Prefix Sum, Last Valid Position
  • Prerequisite: arrays/lists, loops, accumulation variables, indexing, careful output convention
  • What this teaches: 不一定要存完整 prefix array;如果只关心当前累计状态,可以用滚动变量一路更新答案。
  • Where it appears again: prefix sums, range sums, two-array comparisons, sweep-line style accumulation

下一步推荐

如果你已经理解 Sum Game,可以继续看:

  • 相关 CP Weekly 真题:CCC 2025 J4 Sunny Days(prefix/suffix consecutive counts)、CCC 2021 S1 Crazy Fencing(array accumulation,coming soon)、CCC 2020 S3 Searching for Strings(sliding window,coming soon)
  • 相关 Python / C++ 基础:loops and accumulation、lists/vectors、indexing、integer totals
  • 相关 DSA 专题:CCC Prefix and Sliding Window Patterns(planned)

题目要我们做什么

Annie 关注两支棒球队:Swifts 和 Semaphores。赛季一共有 N 天,两队每天各打一场比赛。

输入给出:

N
Swifts 每天得分
Semaphores 每天得分

我们要找最大的整数 K,满足:

Swifts 前 K 天总分 == Semaphores 前 K 天总分

如果从第 1 天到第 N 天结束后都没有出现累计总分相等,就输出:

0

注意:比赛开始前两队总分当然都是 0,但题目要的是 K <= N 的比赛日之后。如果只有开始前相等,答案仍然是 0

初学者容易卡在哪里

第一个误区是只比较每天的单日得分。

比如第 2 天:

Swifts 当天得分 == Semaphores 当天得分

这并不代表前 2 天累计总分相等。题目问的是 prefix sum,也就是从第 1 天加到第 K 天的总和。

第二个误区是看到 “largest K” 就想把所有相等的位置存下来,最后取最大。其实不需要。我们从第 1 天扫到第 N 天,每次发现累计总分相等,就把答案更新成当前天数。扫完以后,变量 answer 自然就是最后一次平局日。

第三个误区是忘记答案可以是 0。如果整个赛季中没有任何一天结束后累计总分相同,就不能输出 1 或其他默认值。

核心算法概念

这题的核心是 running prefix sum。

普通 prefix sum 通常会建立数组:

swift_prefix[i] = Swifts 前 i 天总分
semaphore_prefix[i] = Semaphores 前 i 天总分

但这道题只需要比较“当前这一天”的累计总分,不需要回头查询历史区间,所以不必真的存两个 prefix array。

我们只维护两个变量:

swift_total
semaphore_total

然后每天更新一次:

swift_total += swift_scores[i]
semaphore_total += semaphore_scores[i]

如果更新后相等:

answer = i + 1

这里 i + 1 表示第几天,因为数组下标从 0 开始,但题目里的 K 是从 1 开始数天数。

状态定义

我们在扫描过程中维护三个状态:

swift_total = Swifts 到今天为止的总分
semaphore_total = Semaphores 到今天为止的总分
answer = 目前发现的最后一次累计总分相等的天数

初始时:

swift_total = 0
semaphore_total = 0
answer = 0

answer = 0 很自然,因为如果没有任何比赛日满足条件,最终就应该输出 0。

算法步骤

  1. 读入 N
  2. 读入 Swifts 的 N 个单日得分。
  3. 读入 Semaphores 的 N 个单日得分。
  4. swift_total = 0semaphore_total = 0answer = 0
  5. 从第 1 天扫到第 N 天:
  • 把当天 Swifts 得分加入 swift_total
  • 把当天 Semaphores 得分加入 semaphore_total
  • 如果两个累计总分相等,更新 answer 为当前天数。
  1. 输出 answer

Python 解法

N = int(input())
swift_scores = list(map(int, input().split()))
semaphore_scores = list(map(int, input().split()))

swift_total = 0
semaphore_total = 0
answer = 0

for i in range(N):
    swift_total += swift_scores[i]
    semaphore_total += semaphore_scores[i]

    if swift_total == semaphore_total:
        answer = i + 1

print(answer)

这份代码的关键是:

if swift_total == semaphore_total:
    answer = i + 1

我们不是一发现相等就停止,因为题目要的是最大的 K。继续往后扫,最后一次更新留下来的就是答案。

C++ 解法

#include <iostream>
#include <vector>
using namespace std;

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

    int N;
    cin >> N;

    vector<int> swift(N);
    vector<int> semaphore(N);

    for (int i = 0; i < N; i++) {
        cin >> swift[i];
    }

    for (int i = 0; i < N; i++) {
        cin >> semaphore[i];
    }

    int swiftTotal = 0;
    int semaphoreTotal = 0;
    int answer = 0;

    for (int i = 0; i < N; i++) {
        swiftTotal += swift[i];
        semaphoreTotal += semaphore[i];

        if (swiftTotal == semaphoreTotal) {
            answer = i + 1;
        }
    }

    cout << answer << "\n";
    return 0;
}

C++ 版本也保持同样的思路:一边累加,一边更新最后一次相等的位置。

这题里使用 int 是足够的,因为:

N <= 100000
每天最多 20 分
最大累计分数 <= 2000000

不过在更通用的 prefix sum 题里,如果数值范围更大,应该优先考虑 long long

复杂度分析

我们只扫描两个数组一次。

时间复杂度:

O(N)

如果按上面的写法存下两个数组,空间复杂度是:

O(N)

其实还可以边读边处理,使额外空间降到:

O(1)

但因为输入分成两整行,先读数组再扫描更清晰,也足以通过本题。

常见错误

  1. 比较每天的单日得分,而不是累计总分。
  2. 一发现累计相等就立刻输出,忘记题目要最大的 K
  3. 忘记没有平局日时答案是 0
  4. answer = i 写成 0-indexed,导致答案少 1。
  5. 建了 prefix array 以后比较错位置,例如把第 i 天和前 i 天混淆。
  6. 在更大范围的 prefix sum 题里继续使用 int,造成溢出。

复习问题

  1. 为什么这题比较的是累计总分,而不是当天得分?
  2. 为什么发现相等后不能马上停止?
  3. answer 为什么可以初始化为 0
  4. i + 1i 分别代表什么?
  5. 什么时候需要完整 prefix array,什么时候只需要 running total?

Questions or feedback?

Have a question about this article or want to suggest an improvement? Send us a private message.

Send Feedback

有问题或建议?

如果你对本文有疑问,或希望提出改进建议,请给我们发送私密留言。

发送反馈

Back to CP Weekly Challenge
返回 CP Weekly Challenge

Scroll to Top