当前位置: 首页 > news >正文

【题解】CF1993D

目录

  • 翻译
  • 思路
  • 总代码

翻译

原题链接
在这里插入图片描述

思路

  容易发现,无论如何操作,最后剩下的数量是一定的,记剩下的数组中中位数的位置为 m m m(从1开始记),注意不能将数组删空。有:

剩余数组的长度 L = ( n − 1 ) m o d k + 1 L=(n-1) \mod k + 1 L=(n1)modk+1
m = ( L + 1 ) / 2 m = (L + 1) / 2 m=(L+1)/2

  显然我们需要一个 O ( n l o g n ) O(nlogn) O(nlogn)的算法,根据经验,注意到中位数具有可二分性(显然尽量把小的数删掉中位数肯定大)。所以二分答案中位数是多少,然后 c h e c k check check这个中位数是否可行。

  对于判断环节,我们可以设计一个函数,寻找一种方案,使删除后剩下的数中小于 x x x的最小数量 c n t cnt cnt,那如果 c n t < m cnt < m cnt<m,,则说明存在可行的中位数 y y y,使得 y < x y<x y<x。根据这些,我们可以写出二分的框架:

int count(int x) {return 剩下的数中小于x的最小数量cnt
} int m = ((n-1) % k + 1 + 1) / 2;
int l = 1, r = 1e9, ans=-1;
while(l<=r) {int mid = l+r>>1;if(count(mid) < m) {   // 最少比mid小的数量比m少 ans = mid;l = mid + 1; } else {r = mid - 1;}
} 
cout<<ans<<endl;

  接下来完善 c o u n t count count函数。采用 d p dp dp的方式,记 f [ i ] f[i] f[i]表示到第 i i i个数时小于 x x x的数量的最小值(允许不拿 a [ i ] a[i] a[i]),则:

f [ i ] = m i n ( f [ i − 1 ] + ( a [ i ] < x ? 1 : 0 ) , f [ i − k ] ( i f i > = k ) ) f[i]=min(f[i-1]+(a[i]<x?1:0), f[i-k] \quad (if \quad i>=k)) f[i]=min(f[i1]+(a[i]<x?1:0),f[ik](ifi>=k))

  但这样会有一个问题,如果 k ∣ n k | n kn,则这个 d p dp dp会找到一种方案,将所有数都删除,最终返回 0 0 0
  为了解决这个问题,我们标记一下当前方案是否为空即可,即将 f f f数组新增大小为 2 2 2的一维,最后返回 f [ n ] [ 1 ] f[n][1] f[n][1]。递推式子稍微改一改即可,代码如下:

for(int i=0;i<=n;i++) f[i][0] = f[i][1] = 1e9;
f[0][0] = 0;
for(int i=1;i<=n;i++) {f[i][1] = min(f[i-1][0], f[i-1][1]) + (a[i] < x ? 1 : 0);if(i>=k) {f[i][0] = min(f[i][0], f[i-k][0]);f[i][1] = min(f[i][1], f[i-k][1]);}
} 
return f[n][1];

总代码

#include<bits/stdc++.h>
#define N 500005
using namespace std;
int t, n, k, a[N], f[N][2];
int count(int x) {// 使小于x的数最少// f[i]表示到i,i可以被删除 , 标记是否为空 for(int i=0;i<=n;i++) f[i][0] = f[i][1] = 1e9;f[0][0] = 0;for(int i=1;i<=n;i++) {f[i][1] = min(f[i-1][0], f[i-1][1]) + (a[i] < x ? 1 : 0);if(i>=k) {f[i][0] = min(f[i][0], f[i-k][0]);f[i][1] = min(f[i][1], f[i-k][1]);}} return f[n][1];
} 
int main() {cin>>t;while(t--) {cin>>n>>k;int m = ((n-1) % k + 1 + 1) / 2;  // 第m个数为中位数for(int i=1;i<=n;i++) {cin>>a[i];}int l = 1, r = 1e9, ans=-1;while(l<=r) {int mid = l+r>>1;
//			printf("%d %d\n", mid, count(mid));if(count(mid) < m) {   // 最少比mid小的数量比m少 ans = mid;l = mid + 1; } else {r = mid - 1;}} cout<<ans<<endl;}return 0;
} 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 喧嚣漫天之际,重新审视以太坊的定位与路线图
  • 力扣移除元素(力扣题26)(插空找空位java)
  • 在虚拟机安装mysql数据库
  • 测试工程师学历路径:从功能测试到测试开发
  • selenium元素定位:元素点击交互异常解决方法
  • 计算机网络 --- 【1】欢迎来到计算机网络/计算机网络基本概念/计算机网络、互连网、互联网的区别
  • Vue的slot插槽(默认插槽、具名插槽、作用域插槽)
  • 微服务中间件之Nacos
  • JAVA 的excel数据批量导入解析 现在都用什么API工具 Apache POI 、EasyExcel 、easypoi有什么区别
  • java设计模式 桥接模式
  • kafka之视频和图片文件
  • 闯入清洁家电“诸神之战”的萤石,凭什么立足?
  • Python 工厂模式:构建灵活软件架构的秘密武器
  • 大数据Flink(一百一十六):Flink SQL的时间属性
  • 一文讲懂Mac中的环境变量
  • 收藏网友的 源程序下载网
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • 03Go 类型总结
  • 3.7、@ResponseBody 和 @RestController
  • Django 博客开发教程 8 - 博客文章详情页
  • ES10 特性的完整指南
  • es的写入过程
  • github指令
  • iOS 颜色设置看我就够了
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JavaScript的使用你知道几种?(上)
  • Netty源码解析1-Buffer
  • PV统计优化设计
  • Spark RDD学习: aggregate函数
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 基于 Babel 的 npm 包最小化设置
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 三栏布局总结
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • RDS-Mysql 物理备份恢复到本地数据库上
  • # windows 运行框输入mrt提示错误:Windows 找不到文件‘mrt‘。请确定文件名是否正确后,再试一次
  • $.ajax()方法详解
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (备忘)Java Map 遍历
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (一)Linux+Windows下安装ffmpeg
  • (一)u-boot-nand.bin的下载
  • (原創) 未来三学期想要修的课 (日記)
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)http-server应用
  • .bat批处理(一):@echo off
  • .NET 5种线程安全集合
  • .NET Core中的去虚
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET/C# 的字符串暂存池
  • .NET企业级应用架构设计系列之技术选型