[蓝桥杯]对局匹配

news2025/6/6 19:33:28

对局匹配

题目描述

小明喜欢在一个围棋网站上找别人在线对弈。这个网站上所有注册用户都有一个积分,代表他的围棋水平。

小明发现网站的自动对局系统在匹配对手时,只会将积分差恰好是 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。核心思路是​​分组处理 + 动态规划​​:

  1. ​分组策略​​:将用户按积分模K的余数分成K组(余数0~K-1)
  2. ​组内处理​​:每组内积分值差为K的倍数,避免跨组匹配(差为K的数必同余)
  3. ​链式结构​​:每组内积分排序后,相邻差为K的数形成"冲突链"
  4. ​动态规划​​:在每条冲突链上求解最大独立集(不相邻节点和最大)
    📝 算法步骤
  5. ​特殊处理K=0​​:

    • 直接统计不同积分值数量(每个值只能选1个用户)
    • 例:输入[1,1,2,2] → 不同值{1,2} → 答案=2
  6. ​分组处理(K>0)​​:

    • 创建K个分组桶(余数0~K-1)
    • 遍历每个积分a,放入a % K桶中
    • 例:K=2时,积分[1,3,5]放入余数1桶
  7. ​组内处理​​:

    • 对每组积分排序并合并相同值(记录出现次数)
    • 按积分值差划分连续子链(差=K为连续,否则断开)
    • 例:余数0组[0,2,4,6] → 子链0-2-4-6
  8. ​链上动态规划​​:

    • 状态定义:
      • dp0:不选当前节点的最大和
      • dp1:选择当前节点的最大和
    • 状态转移:
      • 不选当前:new_dp0 = max(dp0, dp1)
      • 选当前:new_dp1 = dp0 + 当前权值
    • 链尾结果:max(dp0, dp1)
  9. ​结果汇总​​:

    • 累加所有组的结果
      🧠 代码实现(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
      • 余1组:[1,3,5,7] → 子链1-3-5-7
        • DP:选1+5或3+7=2
    • 输出: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++) { ... }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2399529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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 作为一款高性…

【Kotlin】简介变量类接口

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

Mybatis入门到精通

一&#xff1a;什么是Mybatis 二&#xff1a;Mybatis就是简化jdbc代码的 三&#xff1a;Mybatis的操作步骤 1&#xff1a;在数据库中创建一个表&#xff0c;并添加数据 我们这里就省略了 2&#xff1a;Mybatis通过maven来导入坐标&#xff08;jar包&#xff09; 3&#xff1a…

Unity性能优化笔记

降低Draw Call 降低draw call&#xff08;unity里叫batches&#xff09;的方法有&#xff1a; 模型减少材质&#xff1b; 多模型共用材质&#xff1b; 烘焙灯光&#xff1b; 关闭阴影和雾&#xff1b; 遮挡剔除&#xff1b; 使用LOD&#xff1b; 模型减少材质 > 见…

BERT vs Rasa 如何选择 Hugging Face 与 Rasa 的区别 模型和智能体的区别

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

Excel 重复项标记,删除重复项时出现未响应的情况

目录 一、重复值标记&#xff1a; 二、删除重复值&#xff1a; 三、未响应问题 一、重复值标记&#xff1a; 方法1&#xff1a;开始 》条件格式 》突出显示单元格规则 》重复值 》设置颜色 》确定 PS&#xff1a;样式可自定义&#xff08;边框、字体、背景填充...&#xff0…

Python:操作 Excel 格式化

🔧Python 操作 Excel 格式化完整指南(openpyxl 与 xlsxwriter 双方案) 在数据处理和报表自动化中,Python 是一把利器,尤其是配合 Excel 文件的读写与格式化处理。本篇将详细介绍两大主流库: openpyxl:适合读取与修改现有 Excel 文件xlsxwriter:适合创建新文件并进行复…

雷卯针对易百纳 SS524多媒体处理演示评估板防雷防静电方案

一、 应用场景 1. 远程视频会议 2. 安防监控 3. 人/车检测 4. 人脸检测、比对 5. 屏幕拼接墙 二、 功能概述 1 四核 ARM Cortex-A7 1.2GHz 2 AI算力 1.0Tops 3 4K30fps 4*1080P30编解码 三、 扩展接口 l RAM&#xff1a;板载 2*DDR4&#xff0c;共 2GB&#xff1b; …

【BUG解决】关于BigDecimal与0的比较问题

这是一个很细小的知识点&#xff0c;但是很容易被忽略掉&#xff0c;导致系统问题&#xff0c;因此记录下来 问题背景 明明逻辑上看a和b都不为0才会调用除法&#xff0c;但是系统会报错&#xff1a;java.lang.ArithmeticException异常&#xff1a; if (!a.equals(BigDecimal…

Spring Bean 为何“难产”?攻克构造器注入的依赖与歧义

本文已收录在Github&#xff0c;关注我&#xff0c;紧跟本系列专栏文章&#xff0c;咱们下篇再续&#xff01; &#x1f680; 魔都架构师 | 全网30W技术追随者&#x1f527; 大厂分布式系统/数据中台实战专家&#x1f3c6; 主导交易系统百万级流量调优 & 车联网平台架构&a…

【Lecture01】动手开发科研智能体(WIN11系统)

1. 配置win11系统中的环境&#xff0c;安装管理器Choco&#xff1a; # 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“ 配置如何正确启动项目?

今天在学习开源项目的时候&#xff0c;在安装依赖时遇到了一个报错 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 "…

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 生态系统中的一款现代化浏览器&#xff0c;专为追求高效、隐私和分布式技术的用户设计。它结合了 Codigger 的分布式架构优势&#xff0c;在速度、安全性和开发者支持方面提供了独特的解决方案&#xff0c;同时确保用户对数据的完全控制。 1. 高性能浏览…

运行shell脚本时报错/bin/bash^M: 解释器错误: 没有那个文件或目录

Windows的换行符为\r\n&#xff0c;而linux换行符为\n。先查看一下文件是什么格式的 :set ff --查询一下格式是什么 由于使用nodepad新建的脚本&#xff0c;首选项中格式设置成了windows&#xff0c;上传到linux中报错。 解决方法 1、nodepad中【设置》首选项】修改为unix&am…

Shiro安全权限框架

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

虚拟现实教育终端技术方案——基于EFISH-SCB-RK3588的全场景国产化替代

一、VR教育终端技术挑战与替代价值 ‌实时交互性能瓶颈‌ 赛扬N100/N150仅支持3DOF渲染&#xff08;延迟&#xff1e;25ms&#xff09;&#xff0c;动态手势识别帧率≤15FPS&#xff0c;难以满足6DOF教学场景需求RK3588 Mali-G610 GPU支持6DOF空间渲染&#xff08;延迟≤12ms&…

网络安全A模块专项练习任务五解析

任务五:Linux 操作系统安全配置-1 任务环境说明: ✓ 服务器场景:LinuxServer:(开放链接) ✓ 用户名:root&#xff0c;密码:123456 ✓ 数据库用户名:root&#xff0c;密码:123456 请对服务器 LinuxServer 按要求进行相应的设置&#xff0c;提高服务器的安全性。 1.设置最小…

Redis初入门

Nosql&#xff1a;Not-Only SQL&#xff08;泛指非关系型数据库&#xff09;&#xff0c;作为关系型数据库的补充 作用&#xff1a;应对基于海量用户和海量数据前提下的数据处理问题 redis&#xff1a;C语言开发的一个开源的高性能键值对数据库 特征&#xff1a; 1、数据之…

(10)Fiddler抓包-Fiddler如何设置捕获Firefox浏览器的Https会话

1.简介 经过上一篇对Fiddler的配置后&#xff0c;绝大多数的Https的会话&#xff0c;我们可以成功捕获抓取到&#xff0c;但是有些版本的Firefox浏览器仍然是捕获不到其的Https会话&#xff0c;需要我们更进一步的配置才能捕获到会话进行抓包。 2.环境 1.环境是Windows 10版…