[语言月赛 202412] 题目名没活了 的题解


记住只在没有思路时使用题解,不要从它复制粘贴代码。请尊重题目和题解的作者。
在解题之前提交题解的代码会导致封禁。

作者: admin

概述

本题要求统计这支队伍最终通过了多少道不同的题目。核心解法是记录每个题目是否出现过"通过"状态:一道题只要存在过 state_i = 1 的提交就算通过,通过之后的提交均为无效提交,不影响结果。

分析
核心观察

一道题目是否算通过,只取决于它是否存在过状态为 1 的提交;通过后的提交(无论状态如何)都是无效的,不会改变"已通过"状态。因此问题等价于:统计所有出现过的题目编号中,至少有一次 state_i = 1 的数量。

思路

维护一个标记数组(或集合),对每条记录,若 state_i = 1,则把 pid_i 标记为已通过。同一道题可能多次通过,重复标记不影响计数。最后统计被标记的题目个数即为答案。

无需模拟"通过后提交无效"的细节——只要某道题出现过一次通过状态,它就计入答案,之后再出现任何提交都不改变这一点。

具体示例

样例中 5 条记录依次为 (1, 0)、(4, 1)、(5, 1)、(2, 1)、(4, 0):4 号题第一次提交即通过,之后 (4, 0) 为无效提交;5、2 号题各通过一次;1 号题只有未通过记录。最终通过的题目为 \{2, 4, 5\},共 3 道。

算法步骤
  1. 读入 n、p,初始化标记数组 passed(大小为 p + 1)全为假。
  2. 循环读入每条记录 pid、state:若 state 为 1,将 passed[pid] 置为真。
  3. 统计 passed 中为真的个数并输出。
复杂度分析

时间:O(n + p)

空间:O(p)

实现注意事项
  • 题目编号从 1 开始,标记数组可开大小为 p + 1 以避免下标偏移。
  • 通过后的无效提交(如样例中的 (4, 0))无需特殊处理,因为状态一旦标记为通过就不会被清除。
  • n, p \le 1000,数据量很小,用标记数组或集合均可。
源代码
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, p;
    cin >> n >> p;
    vector<bool> passed(p + 1, false);
    for (int i = 0; i < n; i++) {
        int pid, state;
        cin >> pid >> state;
        if (state == 1) passed[pid] = true;
    }
    int ans = 0;
    for (int i = 1; i <= p; i++) {
        if (passed[i]) ans++;
    }
    cout << ans << '\n';
    return 0;
}
n, p = map(int, input().split())
passed = set()
for _ in range(n):
    pid, state = map(int, input().split())
    if state == 1:
        passed.add(pid)
print(len(passed))

评论

目前没有评论。