1 条题解

  • 0
    @ 2025-6-13 16:16:46

    线性时间复杂度:

    #include <bits/stdc++.h>
    using namespace std;
    
    /*
     * 线性扫描做法(O(n))
     * -------------------------------------------------------------
     * 思路:
     *  对每条记录 i = 1..n 依次读取
     *    now  : 最近一次出现 “咖啡店最低消费 ≤ p” 的位置
     *    last[c] : 色调 c 上一次出现的位置
     *    cnt[c]  : 色调 c 目前出现过的总次数
     *    sum[c]  : 在当前位置可与当前客栈配对的同色客栈数量
     *
     *  当 now ≥ last[c] 时,说明从上一次同色客栈到当前位置之间
     *  至少存在一家满足 b ≤ p 的咖啡店。此时,当前客栈可以与
     *  之前出现过的全部 cnt[c] 家同色客栈配对,
     *  因而 sum[c] = cnt[c]。
     *
     *  若 now < last[c],区间 (last[c], i) 内没有合法咖啡店,
     *  则 sum[c] 保持上一轮的值(相当于“冻结”)。
     *
     *  每处理一条记录:
     *      1. 如果 b ≤ p,更新 now = i
     *      2. 判断 now 与 last[c] 的关系来更新 sum[c]
     *      3. 把 sum[c] 累加进答案
     *      4. cnt[c]++,last[c] = i
     *
     *  变量均为 O(k) 级别,整体 O(n)。
     */
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int n, k, p;
        if (!(cin >> n >> k >> p)) return 0;
    
        /* k ≤ 50,所以直接按色调大小开数组 */
        vector<int>  last(k, 0);      // 上一次出现该色调的位置
        vector<long long> cnt(k, 0);  // 该色调出现次数
        vector<long long> sum(k, 0);  // 当前可配对数
    
        long long ans = 0;            // 最终答案
        int now = 0;                  // 最近一次 b ≤ p 的位置
    
        for (int i = 1; i <= n; ++i) {
            int c, pri;
            cin >> c >> pri;          // 读入色调与最低消费
    
            if (pri <= p) now = i;    // 更新最近合法咖啡店
    
            /* 若区间 [last[c], i] 内至少有一家合法咖啡店 */
            if (now >= last[c])
                sum[c] = cnt[c];      // 全部历史同色客栈都可配对
    
            ans += sum[c];            // 累加新增合法配对数
    
            ++cnt[c];                 // 当前客栈加入历史
            last[c] = i;              // 更新该色调最后出现位置
        }
    
        cout << ans << '\n';
        return 0;
    }
    
    
    • 1

    信息

    ID
    1143
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    5
    已通过
    1
    上传者