1 条题解
-
0
线性时间复杂度:
#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
- 上传者