题解:学而思编程 库存查询

【题目来源】

学而思编程:库存查询

【题目描述】

某超市有 \(n\) 件商品,每件商品都有一个价格标签,价格是 \(1\) 到 \(10000\) 之间的整数。

现在仓库管理员想快速知道:当顾客询问“价格为 \(p\) 元的商品有多少件”时,能立刻给出答案。

请你编写一个程序,根据商品价格清单,依次回答 \(m\) 次询问。

【输入】

第一行两个整数 \(n,m\),分别表示商品总数和询问次数。

第二行包含 \(n\) 个整数,表示每件商品的价格。

接下来 \(m\) 行,每行一个整数 \(p\),表示一次询问的价格。

【输出】

输出 \(m\) 行,每行一个整数,表示对应价格的商品数量。

【输入样例】

8 5
1 1 3 4 4 4 5 5
1
2
3
4
5

【输出样例】

2
0
1
3
2

【核心思想】

  1. 问题分析:给定 \(n\) 件商品的价格(\(1\)\(10000\) 之间的整数),回答 \(m\) 次询问,每次询问价格为 \(p\) 的商品有多少件。这是一个计数数组 + 离线查询问题,关键在于预处理每个价格的出现次数,实现 \(O(1)\) 回答每次询问。

  2. 算法选择

    • 计数数组cnt[p] 记录价格为 \(p\) 的商品数量
    • 离线预处理:先读取所有商品价格并统计频次,再处理询问
  3. 关键步骤

    • 初始化:读取 \(n\)(商品总数)和 \(m\)(询问次数)
    • 统计频次
      • 遍历 \(i\)\(1\)\(n\)
        • 读取价格 \(p\)
        • cnt[p]++:该价格出现次数加 \(1\)
    • 处理询问
      • 遍历 \(m\) 次:
        • 读取查询价格 \(p\)
        • 输出 cnt[p]:价格为 \(p\) 的商品数量
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n + m)\),统计频次 \(O(n)\),每次查询 \(O(1)\)
    • 空间复杂度:\(O(V)\)\(V = 10000\),计数数组 cnt[1..V]
  5. 计数数组的核心思想

    • 值域确定性:价格范围固定为 \(1\)\(10000\),可用数组直接作为下标,实现 \(O(1)\) 访问
    • 查询与数据分离:先一次性统计所有频次,后续查询无需重新遍历,适合多次询问场景
    • 空间换时间:用 \(O(V)\) 空间存储频次,将每次查询从 \(O(n)\) 优化到 \(O(1)\)
    • 替代方案:若值域大或稀疏,可用 mapunordered_map,但数组在稠密值域下更快
    • 适用于"固定值域 + 多频次查询"类问题,计数数组是最简单高效的预处理方案

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;
const int N = 10005;  // 定义最大范围
int n, m, p, cnt[N];  // 第一个集合数量n,查询次数m,临时值p,计数数组cnt

int main()  // 主函数
{
    cin >> n >> m;  // 输入第一个集合的元素数量和查询次数
    for (int i=1; i<=n; i++)  // 读取第一个集合的所有元素
    {
        cin >> p;  // 输入一个元素
        cnt[p]++;  // 统计该元素的出现次数
    }
    while (m--)  // 处理每个查询
    {
        cin >> p;  // 输入要查询的元素
        cout << cnt[p] << endl;  // 输出该元素在第一个集合中出现的次数
    }
    return 0;  // 程序正常结束
}

【运行结果】

8 5
1 1 3 4 4 4 5 5
1
2
2
0
3
1
4
3
5
2
posted @ 2026-07-05 14:37  团爸讲算法  阅读(3)  评论(0)    收藏  举报