[蓝桥杯]对局匹配
对局匹配
题目描述
小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。
小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是 K 的两名用户匹配在一起。如果两人分差小于或大于 KK,系统都不会将他们匹配。
现在小明知道这个网站总共有 NN 名用户,以及他们的积分分别是 A1,A2,⋯ANA1,A2,⋯AN。
小明想了解最多可能有多少名用户同时在线寻找对手,但是系统却一场对局都匹配不起来(任意两名用户积分差不等于 KK)?
输入描述
输入描述
第一行包含两个个整数 N,KN,K。
第二行包含 NN 个整数 A1,A2,⋯ANA1,A2,⋯AN。
其中,1≤N≤105,0≤Ai≤105,0≤K≤1051≤N≤105,0≤Ai≤105,0≤K≤105。
输出描述
输出一个整数,代表答案。
输入输出样例
示例
输入
10 0
1 4 2 8 5 7 1 4 2 8
输出
6
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
总通过次数: 2604 | 总提交次数: 4404 | 通过率: 59.1%
难度: 困难 标签: 2017, 国赛, 动态规划
对局匹配问题:动态规划解法详解
🌟 算法思路
本问题要求找到最多用户同时在线,但任意两人积分差不等于K。核心思路是分组处理 + 动态规划:
- 分组策略:将用户按积分模K的余数分成K组(余数0~K-1)
- 组内处理:每组内积分值差为K的倍数,避免跨组匹配(差为K的数必同余)
- 链式结构:每组内积分排序后,相邻差为K的数形成"冲突链"
- 动态规划:在每条冲突链上求解最大独立集(不相邻节点和最大)
📝 算法步骤
-
特殊处理K=0:
- 直接统计不同积分值数量(每个值只能选1个用户)
- 例:输入
[1,1,2,2]
→ 不同值{1,2}
→ 答案=2
-
分组处理(K>0):
- 创建K个分组桶(余数0~K-1)
- 遍历每个积分
a
,放入a % K
桶中 - 例:K=2时,积分
[1,3,5]
放入余数1桶
-
组内处理:
- 对每组积分排序并合并相同值(记录出现次数)
- 按积分值差划分连续子链(差=K为连续,否则断开)
- 例:余数0组
[0,2,4,6]
→ 子链0-2-4-6
-
链上动态规划:
- 状态定义:
dp0
:不选当前节点的最大和dp1
:选择当前节点的最大和
- 状态转移:
- 不选当前:
new_dp0 = max(dp0, dp1)
- 选当前:
new_dp1 = dp0 + 当前权值
- 不选当前:
- 链尾结果:
max(dp0, dp1)
- 状态定义:
-
结果汇总:
- 累加所有组的结果
🧠 代码实现(C++)
#include <iostream> #include <vector> #include <algorithm> #include <set> using namespace std;int main() {ios::sync_with_stdio(false);cin.tie(0);int N, K;cin >> N >> K;vector<int> A(N);for (int i = 0; i < N; i++) {cin >> A[i];}// 处理K=0的情况if (K == 0) {set<int> distinct;for (int a : A) distinct.insert(a);cout << distinct.size() << endl;return 0;}// 创建K个分组vector<vector<int>> groups(K);for (int a : A) {groups[a % K].push_back(a);}long long ans = 0;// 处理每个分组for (int r = 0; r < K; r++) {if (groups[r].empty()) continue;// 组内排序sort(groups[r].begin(), groups[r].end());// 合并相同积分并计数vector<pair<int, int>> arr; // (积分值, 出现次数)int cnt = 1;for (int i = 1; i < groups[r].size(); i++) {if (groups[r][i] == groups[r][i-1]) {cnt++;} else {arr.push_back({groups[r][i-1], cnt});cnt = 1;}}arr.push_back({groups[r].back(), cnt});// 划分子链(相邻差为K的连续段)vector<vector<pair<int, int>>> chains;vector<pair<int, int>> chain;chain.push_back(arr[0]);for (int i = 1; i < arr.size(); i++) {if (arr[i].first - arr[i-1].first == K) {chain.push_back(arr[i]);} else {chains.push_back(chain);chain = {arr[i]};}}chains.push_back(chain);// 每条子链动态规划for (auto& ch : chains) {if (ch.empty()) continue;long long dp0 = 0; // 不选前一个节点long long dp1 = ch[0].second; // 选前一个节点for (int i = 1; i < ch.size(); i++) {long long new_dp0 = max(dp0, dp1);long long new_dp1 = dp0 + ch[i].second;dp0 = new_dp0;dp1 = new_dp1;}ans += max(dp0, dp1);}}cout << ans << endl;return 0; }
📊 代码解析
-
输入处理:
- 使用
ios::sync_with_stdio(false)
加速输入 - 一维数组存储积分值
- 使用
-
K=0特判:
- 利用
set
去重统计不同积分数量
- 利用
-
分组管理:
vector<vector<int>> groups(K)
创建分组桶- 模运算
a % K
确定分组
-
组内压缩:
- 排序后合并相同积分,存储为
(值, 频次)
对 - 例:
[2,2,2,4]
→(2,3),(4,1)
- 排序后合并相同积分,存储为
-
子链划分:
- 相邻积分差=K的划为同链
- 例:
[0,2,4,10]
(K=2)→ 子链[0,2,4]
和[10]
-
动态规划优化:
- 滚动变量
dp0
/dp1
代替DP数组 - 空间复杂度O(1)每链,时间复杂度O(N)
- 滚动变量
-
🧪 实例验证
输入1:
K=0
,积分=[1,4,2,8,5,7,1,4,2,8]
- 不同值:
{1,2,4,5,7,8}
- 输出:6 ✓
- 输入2:
K=2
,积分=[0,2,4,1,3,5,7]
- 分组:
- 余0组:
[0,2,4]
→ 子链0-2-4
- DP:节点
(0,1)-(2,1)-(4,1)
- 选0+4=2
- DP:节点
- 余1组:
[1,3,5,7]
→ 子链1-3-5-7
- DP:选1+5或3+7=2
- 余0组:
- 输出:2+2=4 ✓
-
输入3:
K=3
,积分=[1,1,4,4,7,7,10]
- 余1组:
[1,1,4,4,7,7,10]
- 合并:
(1,2),(4,2),(7,2),(10,1)
- 子链:
1-4-7
(差3)和10
- 链1 DP:选1+7=4
- 链2 DP:选10=1
- 合并:
- 输出:4+1=5 ✓
-
⚠️ 注意事项
-
边界处理:
- K=0需单独处理
- 空分组直接跳过
- 单元素链直接取权值
-
数据类型:
- 结果用
long long
防溢出(最大1010) - 积分值范围0-105,用
int
存储
- 结果用
-
性能关键:
- 排序复杂度O(N log N)
- 链划分和DP均O(N)
- 整体复杂度O(N log N)
-
特殊测试点:
测试类型 测试数据 预期结果 K=0 [1,1,2,2] 2 K>最大积分 K=100000, [1,2,3] 3 全相同积分 K=1, [5,5,5] 3 不连续子链 K=2, [0,3,6,10,13] 4 超大随机数据 N=100000, K=50000 通过1s限 -
💡 优化建议
-
合并相同值优化:
// 使用map避免排序后遍历 unordered_map<int, int> freq; for (int a : groups[r]) freq[a]++; for (auto& p : freq) arr.push_back(p); sort(arr.begin(), arr.end());
-
链划分与DP合并:
long long chainDP = 0; long long prev0 = 0, prev1 = freq[arr[0]]; for (int i = 1; i < arr.size(); i++) {if (arr[i] - arr[i-1] == K) {// DP计算...} else {chainDP += max(prev0, prev1);prev0 = 0; prev1 = freq[arr[i]];} }
-
内存优化:
- 用
vector<vector<int>>().swap(groups)
及时释放内存 - 使用
reserve()
预分配分组空间
- 用
-
并行化潜力:
- 不同分组可并行处理
- 使用OpenMP加速:
#pragma omp parallel for reduction(+:ans) for (int r=0; r<K; r++) { ... }
- 累加所有组的结果
相关文章:

[蓝桥杯]对局匹配
对局匹配 题目描述 小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。 小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是 K 的两名用户匹配在一起。如果两人分差小于或大于 KK,…...
BBU 电源市场报告:深入剖析与未来展望
在当今数字化时代,数据中心的稳定运行至关重要。BBU 电源作为保障数据中心设备在停电或电压下降期间临时电力供应的关键系统,其市场发展备受关注。本文将从市场规模、竞争格局、产品类型、应用领域等多个维度对 BBU 电源市场进行深入分析,并为…...

Redis 持久化机制详解:RDB 与 AOF 的原理、优缺点与最佳实践
目录 前言1. Redis 持久化机制概述2. RDB 持久化机制详解2.1 RDB 的工作原理2.2 RDB 的优点2.3 RDB 的缺点 3. AOF 持久化机制详解3.1 AOF 的工作原理3.2 AOF 的优点3.3 AOF 的缺点 4. RDB 与 AOF 的对比分析5. 持久化机制的组合使用与最佳实践6. 结语 前言 Redis 作为一款高性…...
Hadoop企业级高可用与自愈机制源码深度剖析
Hadoop企业级高可用与自愈机制源码深度剖析 前言 在大数据平台生产环境中,高可用(HA)与自动化自愈能力直接决定了数据安全与服务稳定性。本文结合源码与实战,深入剖析Hadoop生态中YARN高可用、HDFS自动扩容、故障自愈三大核心机…...

【Kotlin】简介变量类接口
【Kotlin】简介&变量&类&接口 【Kotlin】数字&字符串&数组&集合 【Kotlin】高阶函数&Lambda&内联函数 【Kotlin】表达式&关键字 文章目录 Kotlin_简介&变量&类&接口Kotlin的特性Kotlin优势创建Kotlin项目变量变量保存了指向对…...

Mybatis入门到精通
一:什么是Mybatis 二:Mybatis就是简化jdbc代码的 三:Mybatis的操作步骤 1:在数据库中创建一个表,并添加数据 我们这里就省略了 2:Mybatis通过maven来导入坐标(jar包) 3:…...

Unity性能优化笔记
降低Draw Call 降低draw call(unity里叫batches)的方法有: 模型减少材质; 多模型共用材质; 烘焙灯光; 关闭阴影和雾; 遮挡剔除; 使用LOD; 模型减少材质 > 见…...

BERT vs Rasa 如何选择 Hugging Face 与 Rasa 的区别 模型和智能体的区别
我在之前的一篇文章中提到我的短期目标的问题,即想通过Hugging Face的BERT或Rasa搭建一个简单的意图识别模型,针对发票业务场景来展示其效果 [如:开发票、查询发票]。 开篇,有必要记录几个英文缩写或术语 (如果喜欢&a…...

Excel 重复项标记,删除重复项时出现未响应的情况
目录 一、重复值标记: 二、删除重复值: 三、未响应问题 一、重复值标记: 方法1:开始 》条件格式 》突出显示单元格规则 》重复值 》设置颜色 》确定 PS:样式可自定义(边框、字体、背景填充...࿰…...
CppCon 2015 学习:Beyond Sanitizers
Sanitizers,一类基于编译时插桩(instrumentation)的动态测试工具,用来检测程序运行时的各种错误。 Sanitizers 简介 基于编译时插桩:编译器在编译代码时自动插入检测代码。动态运行时检测:程序运行时实时…...
Mysql选择合适的字段创建索引
1. 考虑字段的选择性 选择性:字段的选择性是指字段中不重复值的比例。选择性越高(即不重复值越多),索引的效率越高。 示例: 如果一个字段有100万行数据,但只有2个不重复值(如性别字段ÿ…...

Python:操作 Excel 格式化
🔧Python 操作 Excel 格式化完整指南(openpyxl 与 xlsxwriter 双方案) 在数据处理和报表自动化中,Python 是一把利器,尤其是配合 Excel 文件的读写与格式化处理。本篇将详细介绍两大主流库: openpyxl:适合读取与修改现有 Excel 文件xlsxwriter:适合创建新文件并进行复…...
ant-design-vue select 下拉框不好用解决
将optionFilterProp设置为label和a-select-option的:label"item.name"自定义属性 <a-selectshowSearchallowClearoptionFilterProp"label"placeholder"请选择选项"style"width: 120px; margin-right: 16px"><a-select-optio…...
[Java 基础]创建人类这个类小练习
请根据如下的描述完成一个小练习: 定义一个名为 Human 的 Java 类在该类中定义至少三个描述人类特征的实例变量(例如:姓名、年龄、身高)为 Human 类定义一个构造方法,该构造方法能够接收所有实例变量作为参数…...
Day43 Python打卡训练营
作业: kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化 进阶:并拆分成多个文件 选取Kaggle上的CIFAR-10数据集进行CNN训练,并使用Grad-CAM进行可视化,代码将拆分为多个文件以保持模块化。CIFAR-10是…...

雷卯针对易百纳 SS524多媒体处理演示评估板防雷防静电方案
一、 应用场景 1. 远程视频会议 2. 安防监控 3. 人/车检测 4. 人脸检测、比对 5. 屏幕拼接墙 二、 功能概述 1 四核 ARM Cortex-A7 1.2GHz 2 AI算力 1.0Tops 3 4K30fps 4*1080P30编解码 三、 扩展接口 l RAM:板载 2*DDR4,共 2GB; …...

【BUG解决】关于BigDecimal与0的比较问题
这是一个很细小的知识点,但是很容易被忽略掉,导致系统问题,因此记录下来 问题背景 明明逻辑上看a和b都不为0才会调用除法,但是系统会报错:java.lang.ArithmeticException异常: if (!a.equals(BigDecimal…...

Spring Bean 为何“难产”?攻克构造器注入的依赖与歧义
本文已收录在Github,关注我,紧跟本系列专栏文章,咱们下篇再续! 🚀 魔都架构师 | 全网30W技术追随者🔧 大厂分布式系统/数据中台实战专家🏆 主导交易系统百万级流量调优 & 车联网平台架构&a…...
LeetCodeHot100(图论篇)
目录 图论岛屿数量题目代码 腐烂的橘子题目代码 课程表题目代码 实现 Trie (前缀树)题目代码 后续内容持续更新~~~ 图论 岛屿数量 题目 给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数…...

【Lecture01】动手开发科研智能体(WIN11系统)
1. 配置win11系统中的环境,安装管理器Choco: # Download and install Chocolatey: powershell -c "irm https://community.chocolatey.org/install.ps1|iex" # Download and install Node.js: choco install nodejs-lts --version"22&qu…...

“packageManager“: “pnpm@9.6.0“ 配置如何正确启动项目?
今天在学习开源项目的时候,在安装依赖时遇到了一个报错 yarn add pnpm9.6.0 error This projects package.json defines "packageManager": "yarnpnpm9.6.0". However the current global version of Yarn is 1.22.22.Presence of the "…...
Git Github Gitee GitLab
Git的工作流程 工作区(Workspace):电脑本地目录,即平时存放项目代码的地方 暂存区(Index/Stage):临时存放改动信息的地方 本地仓库(Repository):存放所有提交的版本数据 远程仓库(Remote):托管代码的服务器&#x…...
华为设备OSPF配置与实战指南
一、基础配置架构 sysname HUAWEI-ABR ospf 100 router-id 1.1.1.1area 0.0.0.0network 10.1.1.0 0.0.0.255 # 将接口加入区域0 interface GigabitEthernet0/0/1ospf enable 100 area 0.0.0.0 # 华为支持点分十进制区域号bandwidth-reference 10000 # 设置10Gbps参考带宽…...

Paraformer分角色语音识别-中文-通用 FunASR
https://github.com/modelscope/FunASR/blob/main/README_zh.md https://github.com/modelscope/FunASR/blob/main/model_zoo/readme_zh.md PyTorch / 2.3.0 / 3.12(ubuntu22.04) / 12.1 Paraformer分角色语音识别-中文-通用 https://www.modelscope.cn/models/iic/speech_p…...

Spitfire:Codigger 生态中的高性能、安全、分布式浏览器
Spitfire 是 Codigger 生态系统中的一款现代化浏览器,专为追求高效、隐私和分布式技术的用户设计。它结合了 Codigger 的分布式架构优势,在速度、安全性和开发者支持方面提供了独特的解决方案,同时确保用户对数据的完全控制。 1. 高性能浏览…...
vimadbgit命令
vim 全部选中 全选(高亮显示):按esc后,然后ggvG或者ggVG 全部复制:按esc后,然后ggyG 全部删除:按esc后,然后dG -----------------------------------------------------------------…...

运行shell脚本时报错/bin/bash^M: 解释器错误: 没有那个文件或目录
Windows的换行符为\r\n,而linux换行符为\n。先查看一下文件是什么格式的 :set ff --查询一下格式是什么 由于使用nodepad新建的脚本,首选项中格式设置成了windows,上传到linux中报错。 解决方法 1、nodepad中【设置》首选项】修改为unix&am…...
2506,wtl的通知事件
通知事件 最后一步,通知(连接)控件CMainDlg想要接受的浏览器控件触发的消息.连接在OnInitDialog(),断开在OnDestroy(). VC6中连接 VC6中,ATL的全局函数,AtlAdviseSinkMap()通知(连接)对话框中所有控件开始或终止发送事件到C对象. 该该函数的第一个参数是一个指向拥有事件映射…...

Shiro安全权限框架
①、添加依赖 ②、创建ini文件 获取权限相关信息可以通过数据库获取,也可以通过ini配置文件获取 ③、认证代码 public class ShiroRun{public static void main(){//初始化获取SecurityManagerIniSerucityManagerFactory factory new IniSecurityManagerFac…...

虚拟现实教育终端技术方案——基于EFISH-SCB-RK3588的全场景国产化替代
一、VR教育终端技术挑战与替代价值 实时交互性能瓶颈 赛扬N100/N150仅支持3DOF渲染(延迟>25ms),动态手势识别帧率≤15FPS,难以满足6DOF教学场景需求RK3588 Mali-G610 GPU支持6DOF空间渲染(延迟≤12ms&…...