固定右端点后,合法左端点只取决于它是否落在最近一家消费不超过 p 的客栈之前;一趟 O(n) 扫描按色调计数即可统计全部方案。
OJ: roj
题目 ID: 3589
难度:普及
标签:计数思维python
创建: 2026-10-02 09:16
更新: 2026-10-07 13:50
题目描述
- 色调相同
; - 区间
内至少有一家咖啡店消费不超过 。
输入:
输出:合法方案总数。
数据范围:
样例:
思路
固定右端点 total[c](该色已出现次数)、valid[c](位置 pending(ans += total[c] 并清空 pending 补入 valid;否则 ans += valid[c] 并把
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-02 09:16
# update_at: 2026-10-02 09:16
import sys
def solve() -> None:
data = iter(map(int, sys.stdin.buffer.read().split()))
n, k, p = next(data), next(data), next(data)
total = [0] * k # 每种色调已经出现过的客栈数
valid = [0] * k # 每种色调中「位置不超过最近一家低价店」的客栈数
pending: list[int] = [] # 最近一家低价店之后出现的色调,还没计入 valid
ans = 0
for _ in range(n):
color, price = next(data), next(data)
if price <= p:
# 本店就是低价店:任何之前的同色客栈与它配对都合法(区间含右端点)
ans += total[color]
# 上次低价店到本店之间的客栈,现在都落在最新低价店左侧(含),补计入
for col in pending:
valid[col] += 1
pending.clear()
valid[color] += 1 # 本店自身也是低价店,对更靠右的客栈可用
else:
# 区间内要有低价店,只有位置在最近低价店左侧(含)的同色客栈才可配对
ans += valid[color]
pending.append(color)
total[color] += 1
print(ans)
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 14:42
* update_at: 2026-10-06 14:42
*/
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int MAXK = 10005; // 色调数上限
int n, k;
ll p;
int total[MAXK]; // 每种色调已出现的客栈数
int valid[MAXK]; // 每种色调中位置不超过最近低价店的客栈数
int pending[MAXK]; // 暂存最近低价店之后出现的色调,补记时一次性处理
int pending_cnt; // pending 当前长度
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> k >> p;
ll ans = 0;
for (int i = 1; i <= n; ++i) {
int color;
ll price;
cin >> color >> price;
if (price <= p) {
// 本店是低价店:之前所有同色客栈都与它合法
ans += total[color];
// 把 pending 里的客栈全部补入 valid
for (int j = 0; j < pending_cnt; ++j) {
valid[pending[j]]++;
}
pending_cnt = 0;
valid[color]++; // 本店自身对更右侧客栈可用
} else {
// 只能与最近低价店左侧(含)的同色客栈配对
ans += valid[color];
pending[pending_cnt++] = color;
}
total[color]++;
}
cout << ans << "\n";
return 0;
}