P10098 [ROIR 2023] 地铁建设 (Day 2)

Unity程序化河流生成工具Waterways:从算法到实践的全流程解析 程序化内容生成(PCG)是游戏开发与三维建模领域的关键技术,它通过算法自动创建游戏内容,显著提升开发效率。其核心原理是将设计规则转化为可执行的代码逻辑,从而生成复杂、多样且符合自然规律的环境资产。在开放世界游戏和模拟经营类项目中,程序化生成技术能够快速构建大规模、高一致性的自然场景,如山川、森林与水体网络。Unity引擎作为广泛使用的开发平台,其地形系统与着色器管线为程序化工具的集成提供了强大基础。本文聚焦于利用Waterways这一Unity工具集,深入探讨如何通过模拟重力驱动、流量累积等自然水力原理,在 阅读详情

记录147

#include<bits/stdc++.h>
using namespace std;
#define ll long long // 使用long long处理大数

const int MAXN=105;
int n;
ll p;
ll z[MAXN],a[MAXN],b[MAXN]; // 存储每个发动机的参数

// 验证函数:判断电压为x时,总功率是否>=p
bool check(ll x) {
    ll total_power=0;
    for(int i=1;i<=n;i++) {
        if(x<=z[i]) {
            // 第一模式:功率 = a_i * x
            total_power+=a[i]*x;
        } else {
            // 第二模式:功率 = a_i * z_i + b_i * (x - z_i)
            total_power+=a[i]*z[i]+b[i]*(x-z[i]);
        }
        // 剪枝:如果当前总功率已经达到p,直接返回true,防止溢出
        if(total_power>=p) return true;
    }
    return total_power>=p;
}

int main() {
    ios::sync_with_stdio(false); // 关闭同步,加速IO
    cin.tie(0);
    
    cin>>n>>p;
    for(int i=1;i<=n;i++) {
        cin>>z[i]>>a[i]>>b[i];
    }
    
    // 二分答案:寻找满足条件的最小电压
    ll left=1,right=(ll)2e12,ans=right; // 上界设为2*10^12

    while(left<=right) {
        ll mid=(left+right)/2;
        if(check(mid)) { // 如果mid可行,尝试更小的电压
            ans=mid;
            right=mid-1;
        } else { // 如果mid不可行,需要更大的电压
            left=mid+1;
        }
    }
    
    cout<<ans<<"\n";
    return 0;
}
  //2e12 在 C++ 中默认是一个 double(浮点数)类型。当你把它赋值给 long long 类型的变量(比如 right)时,编译器会自动把它转换为整数。
//它也是用 64 个二进制位来存一个小数。但它采用了“科学计数法”的存储方式(1位符号位 + 11位指数位 + 52位尾数位)。因为指数位能表示极大的范围,大概1e15

题目传送门https://www.luogu.com.cn/problem/P10098


前言

我是一名专注信奥赛(CSP-J/S、NOIP)的教练。

  • 如果你觉得这篇题解对你有帮助,欢迎点击关注我的优快云账号,我会持续更新高质量算法解析。
  • 我深知算法思维的构建远比单纯通过题目更重要,本系列题解不局限于AC代码的堆砌,而是致力于拆解题目背后的逻辑链条与核心知识点
  • 备赛路上若遇瓶颈,欢迎随时评论或私信,我将甄选典型疑难问题,通过视频讲解或撰写专项文章的形式,为你提供深度答疑。

核心解题思路

这道题是一道非常经典的二分答案 + 贪心验证问题。

  1. 问题转化与单调性分析:
    题目要求找到“最小的 L”,使得能在 k 次操作内关掉所有的灯。直接去求这个最小 L 比较困难,但如果我们反过来思考:假设 L 已经确定,我们能不能判断 k 次操作够不够?
    这里存在一个关键的单调性:如果长度为 L 的操作能够完成任务,那么长度为 L+1 的操作一定也能完成任务(因为覆盖范围更大了,只会让关灯更容易)。这种单调性为使用“二分答案”提供了完美的理论基础。

  2. 算法设计(二分 + 贪心):

    • 二分答案:L 的取值范围在 [1, n] 之间。我们在该区间内进行二分查找。
    • 贪心验证(check函数):对于当前假设的 L,我们需要判断 k 次操作是否足够。这里采用最直观的贪心策略:从左到右扫描灯的状态,一旦遇到一盏亮着的灯('1'),就必须以这盏灯为起点,执行一次关灯操作。因为如果不关掉这盏灯,后续的操作(起点在更右边)永远无法覆盖到它。这种“见亮必关,且尽量靠左关”的策略,是保证操作次数最少的最优解。

 代码分块详细解释

1. 头文件、全局变量与贪心验证函数

#include<bits/stdc++.h>
using namespace std;
#define ll long long // 使用 long long 防止溢出
int n, k;
string s; // 存储灯的初始状态

// 验证函数:判断长度为 L 的操作是否能在 k 步内关灯
bool check(int L) {
    // 复制一份原始灯的状态,因为验证过程会修改灯的状态
    string temp = s;
    int ops = 0; // 记录操作次数
    
    for(int i = 0; i < n; i++) {
        // 如果当前灯是亮的,必须进行一次操作
        if(temp[i] == '1') {
            ops++;
            if(ops > k) return false; // 操作次数超限,直接返回 false
            
            // 贪心:从当前位置 i 开始,往后关掉 L 盏灯
            for(int j = i; j < i + L && j < n; j++) {
                temp[j] = '0';
            }
        }
    }
    return true; // 操作次数在 k 以内,返回 true
}
  • 详细分析:check 函数是本题的核心。
    • 状态备份:因为验证过程会实际模拟关灯(将 '1' 变为 '0'),为了不破坏原始数据 s,必须使用 temp 进行备份。
    • 贪心模拟:从左往右遍历 temp。当遇到 temp[i] == '1' 时,说明这盏灯还没被关掉。根据贪心原则,我们必须在位置 i 执行一次操作。操作次数 ops 加 1,如果超过 k 直接返回失败。
    • 关灯操作:从位置 i 开始,将接下来连续的 L 盏灯全部置为 '0'。注意边界条件 j < n,防止数组越界。

2. 主函数:多组测试与二分框架

int main() {
    ios::sync_with_stdio(false); // 关闭同步,加速 IO
    cin.tie(0);
    
    int T;
    cin >> T;
    while(T--) {
        cin >> n >> k;
        cin >> s;
        
        // 二分答案:寻找最小的 L
        int left = 1, right = n, ans = n;
        while(left <= right) {
            int mid = (left + right) / 2;
            if(check(mid)) { // 如果 mid 可行,尝试更小的 L
                ans = mid;
                right = mid - 1;
            } else { // 如果 mid 不可行,需要更大的 L
                left = mid + 1;
            }
        }
        
        cout << ans << "\n";
    }
    
    return 0;
}
  • 详细分析:主函数处理了多组测试数据,并搭建了标准的二分答案框架。
    • 二分边界:L 的最小可能值是 1,最大可能值是 n(一次操作关所有灯)。
    • 收缩逻辑:如果 check(mid) 返回 true,说明当前的 L 是可行的,但这不一定是“最小”的,所以我们将 ans 记录为 mid,并尝试在左半区间(更小的 L)继续寻找(right = mid - 1)。如果返回 false,说明 L 太小了,k 次操作根本关不完,必须增大 L(left = mid + 1)。

核心逻辑总结表

代码模块核心变量/操作精炼作用解决的痛点
状态备份string temp = s复制原始灯的状态保证每次 check 验证时,都是基于原始的亮灯状态进行模拟
贪心策略if(temp[i]=='1') 触发操作遇到亮灯就立刻以它为起点关灯确保了在给定 L 的情况下,使用的操作次数是最少的
边界防护j < i+L && j < n限制关灯操作的右边界防止在扫描到数组末尾时,执行 j < i+L 导致数组越界访问
二分框架left=1, right=n在 [1, n] 范围内二分 L利用 L 的单调性,将寻找最优解的时间复杂度降低到 O(n log n)
答案更新ans=mid; right=mid-1记录可行解并向左搜索保证了最终输出的 ans 是满足条件的“最小” L
C#上位机实战:手把手搭智慧工业数字孪生系统,从设备建模到实时联动全落地 字段长度(字节)说明起始标识2固定为0xAA55,用于判断数据包开始设备ID4唯一标识设备(比如1001代表电机1)数据类型10=布尔(启停),1=浮点数(转速/温度)数据长度4数据字节数(布尔1字节,浮点数4字节)数据内容N实际数据(按数据长度读取)校验位1前面所有字节的异或校验,防止数据篡改结束标识2固定为0x55AA,用于判断数据包结束。 阅读详情

相关推荐

别再只盯着报点率了:聊聊电容触摸屏算法里那些不为人知的‘软实力’

本文深入探讨了电容触摸屏算法中常被忽视的‘软实力’,包括环境噪声干扰、信号衰减补偿和多物理场耦合等核心挑战。通过对比消费电子与工业场景的算法需求,揭示了触摸算法在不同应用中的技术分野。文章还提供了实用的算法评估方法和前沿发展趋势,帮助开发者全面了解电容触摸屏技术的隐秘战场。

weixin_42524276的博客 391

洛谷 P10098 [ROIR 2023 Day 2] 地铁建设

换句话说,当电压为 xx 单位电压,如果第 ii 个发动机处于第一模式下,它以 ai×xai​×x 的单位功率运行;如果处于第二模式下,它以 ai×zi+bi×(x−zi)ai​×zi​+bi​×(x−zi​) 的单位功率运行。每个发动机有两种模式,假设所有发动机接收到的电压都为 xx,则当 x≤zix≤zi​ 时第 ii 个发动机在第一模式下工作,否则它在第二模式下工作。//如果功率大于了p表示x大了。

2403_88223186的博客 1042

​苹果开发者账号推送证书配置详细指南​

推送证书的配置是iOS应用实现消息推送的核心步骤。通过生成证书、配置描述文件、集成到服务器三大环节,开发者可快速为App启用APNs服务。建议优先使用更灵活的APNs Auth Key替代传统证书,以减少维护成本。确保拥有有效的苹果开发者账号(个人/公司账号),年费已缴纳。

2328

打卡信奥刷题(786)用C++信奥P10098[普及组/提高] [ROIR 2023] 地铁建设 (Day 2)

翻译自。用于铺设地铁隧道的盾构机有n个发动机。所有发动机是并联的,所以所有发动机两端的电压都相同。每个发动机有两种模式,假设所有发动机接收到的电压都为x,则当x≤zi​时第i个发动机在第一模式下工作,否则它在第二模式下工作。第i个发动机在第一模式下的单位电流为ai​,在第二模式下的单位电流为bi​。所以,根据PUI,当发动机处于第一模式时,每增加1单位电压,其功率增加ai​单位;当发动机处于第二模式时,每增加1单位电压,其功率增加bi​单位。

Loge谈信奥--一个专注于信奥人的博客 4811

工业4.0 底层逻辑

工业4.0 的概念已经被滥用了,它与物联网,工业物联网等概念一样,几乎什么都往里面装。演变成了一句口号和愿景。许多人并不清楚工业4.0的底层逻辑到底是什么?如何遵循工业4.0 的思想构建新一代智能制造系统?并没用清晰地展示工业4.0的技术路线图。

姚家湾博客 1996

在 SAP S/4HANA 分析模型中添加 Measures,Calculated、Restricted、Currency Conversion 与 Unit Conversion 的建模思路

摘要: SAP S/4HANA分析查询建模中,度量(measure)的加工层级是关键难点,涉及聚合时机、币种/单位语义、过滤上下文等复杂因素。度量不仅是数字字段,还需处理计算口径(Calculated Measures)、上下文绑定(Restricted Measures)和单位转换等问题。Calculated Measures适合派生指标(如毛利率),需注意聚合前后计算差异;Restricted Measures通过固化过滤条件(如区分实际/计划金额)确保业务语义一致性。建模时应将业务逻辑下沉到分析模型层

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1025

P10098 [ROIR 2023 Day 2] 地铁建设

【代码】P10098 [ROIR 2023 Day 2] 地铁建设。

GordrnGhost的博客 568

Altium Designer(AD)仿真实验操作指南

1:运行仿真2:设置仿真3:放置电源模块4:放置器件模块5:探针。

XU157303764的博客 8903

备战蓝桥之二分答案

【代码】备战蓝桥之二分答案。

m0_73862548的博客 338

mabl:AI原生测试自动化平台的基础使用

mabl是一个基于人工智能和机器学习的云原生测试自动化平台。它通过使用先进的技术,如机器学习,自动创建和执行测试,自动分析测试结果,并根据需求的变化自动适配和维护测试。这样的自动化过程极大地提高了软件测试的效率和准确性。mabl的口号是 “You write code, mabl tests”,意味着开发者只需关注编写代码,而测试工作则可以交给mabl来完成。mabl的平台支持多种测试类型,包括 Web、App、Api、可访问性和性能测试,使得团队能够更快速、更有信心地发布软件。

blues_C的博客 3661

CPU 访问外设的两种核心机制:MMIO(Memory-Mapped I/O) 和 DMA(Direct Memory Access)

BAR和DMA是计算机系统中两种关键的数据传输机制:BAR(基址寄存器)用于CPU与设备间的控制通信,映射设备寄存器便于配置操作;而DMA(直接内存访问)允许设备直接读写系统内存,无需CPU参与大量数据传输。典型场景如NVMe SSD读取数据时,CPU通过BAR下发指令,设备通过DMA高效传输数据到主机内存,最后中断通知CPU。虽然BAR能映射大内存空间,但仍无法替代DMA的高效数据传输功能,两者各司其职——BAR负责控制,DMA专注数据传输,共同实现高性能的硬件交互。

MHD0815的博客 238

【数据结构】基于比较的排序算法 - 交换排序

本文介绍交换排序中的冒泡排序与快速排序。冒泡排序通过相邻元素比较交换,实现升序,时间复杂度最坏为O(N²),空间复杂度O(1),稳定且适合小规模有序数据。快速排序采用分治思想,以基准值划分区间,平均时间复杂度O(N log N),空间复杂度O(log N),但不稳定,实际应用中性能优异,可通过随机基准、小区间优化等提升效率。

careathers的博客 373

PyTorch深度学习项目实战100例数据集

最近很多订阅了的用户私信咨询有些数据集下载不了以及一些文章中没有给出数据集链接,为了解决这个问题,专门开设了本篇文章,提供数据集下载链接,打包100例的所有数据集。本专栏适用人群:深度学习初学者,专栏将具体讲解如何快速搭建深度学习模型用自己的数据集实现深度学习小项目。 本专栏整理了《PyTorch深度学习项目实战100例》,内包含了各种不同的深度学习项目,包含项目原理以及源码,每一个项目实例都附带有完整的代码+数据集。

优快云 精品推荐 2万+

【数据结构-5】单链表的实现

单链表,具体来说是单向的、不带头的、不循环的链表。链表由一个一个节点组成,每个节点分为数据域和指针域,数据域存放数据,指针域存放下一节点的地址。这样,就可以根据指针域中的地址找到下一个节点,节点就串起来了构成了单链表。

a bit 210

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

C# 数据结构和特殊类型

.NET Core(现称.NET)提供丰富数据结构,优化性能与开发效率。日常开发首选List<T>和Dictionary<TKey,TValue>;高性能场景推荐Span<T>与Memory<T>减少内存分配;并发环境使用ConcurrentDictionary等线程安全集合;避免非泛型集合如ArrayList。

cccloveforever的博客 721

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

pandas 深度入门:从数据结构到一份真实销售报表

本文系统讲解Pandas核心应用,从三分钟安装到完整月度报表生成,涵盖数据读取、清洗、筛选、分组聚合、表连接、透视表与时间序列等13个关键环节。强调“先看数据再动手”,掌握Series/DataFrame/Index结构本质,熟练运用loc/iloc、merge校验、agg/transform区别,通过真实案例实现高效报表自动化,告别手动Excel操作。最后提供性能优化与高频报错解决方案,助力读者快速上手,真正实现“写二十行代码,跑三秒出结果”。

信息安全领域优质创作者|操作系统领域专家 310

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

C++ 数据结构与面向对象:二叉搜索树实现与多态虚函数详解

本文系统讲解二叉搜索树(BST)的迭代实现与C++多态及虚函数底层原理。BST通过非递归方式实现插入、查找、删除,核心在于维护有序性,删除分三种情况处理,替换法为关键技巧。多态基于虚函数表(vtable)与虚函数指针(vfptr),通过基类指针调用重写函数实现运行时动态绑定,需满足继承与虚函数重写条件。抽象类强制接口规范,虚函数表存储函数地址,子类继承或覆盖对应项。二者分别体现数据结构高效性与面向对象灵活性,是C++核心知识点。

2603_95129722的博客 201

数据结构的基本概念和算法的初步认识

本文系统阐述数据结构与算法的基础概念,涵盖数据、数据元素、数据对象的层次关系,数据结构的三要素(逻辑结构、存储结构、数据运算),以及抽象数据类型。重点解析算法的特性与设计要求,并深入讲解时间复杂度分析的核心——大O表示法,通过“只保留最高阶项、忽略常数系数、取最坏情况”三大原则,结合实例剖析O(1)、O(n)等常见时间复杂度,揭示算法效率的本质评估方法。

ACH_YYX的博客 201

【数据结构】堆(Heap):堆的实现、建堆与堆排序

堆是一种特殊的完全二叉树,分为大堆(父节点≥孩子)和小堆(父节点≤孩子),可快速获取最值。堆通常用数组存储,通过下标计算父子关系。核心操作为向上调整(插入时)和向下调整(删除或建堆时),时间复杂度均为O(log N)。建堆可采用从后往前的向下调整法,整体复杂度为O(N)。基于堆的堆排序通过反复提取最大值实现升序排列,总时间复杂度为O(N log N),空间复杂度O(1),是高效稳定的排序算法。

2501_93577780的博客 361

Redis 数据结构、单线程架构与 String 字符串详解

Redis采用单线程架构,通过事件循环(Event Loop)高效处理I/O事件,避免阻塞。其核心优势在于内存操作快、无上下文切换开销。数据结构支持多种内部编码(如ziplist、quicklist),自动根据场景优化存储与性能。字符串类型是基础且灵活,可存文本、数字或二进制数据,最大512MB,支持原子操作。命令如SET、GET、MGET、MSET等实现高效读写,适用于缓存、计数、会话管理等场景。

2303_77004089的博客 366

笔记-论数据结构3(算法分析-时间复杂度)

i <= n;s = 0;次数1234ti1248?i2^02^12^22^32^t-1在遍历的过程中,2^t-1次方的增长率肯定大于n,可得出结论2^t-1 > n那么,为了得出t和n的关系,我们可以运用对数关系:log2为底2^t-1 > log2为底n消掉log2为底2t-1 > log2为底nt > log2为底n+1于是可以得出。

fish_zzzz的博客 239

J1939 DM1 报文数据结构详解:单帧、BAM、CMDT 逐字节拆解与 DTC 跨包问题

1. 一条报文,两套字节结构 DM1 装的是灯具状态加一串 DTC,而串的长度决定哪一种字节结构上线。 8 字节以内是一帧 :两个灯具字节,之后每 DTC 四字节,末尾补齐。超过 8 字节就变成 的一帧 TP.CM 声明

废柴程序员-熊熊的博客 125

数据结构:二叉树,递归转迭代

二叉树的先序遍历,不需要额外信息保存,因为不用返回到父节点,因为已经处理完了,右左右子节点已在栈上,信息够了。而中序与后序是需要保存额外信息的。通用方法中,用一个栈帧保存当前的一些数据,比如局部变量,返回值等,完全是机械式翻译。

憧憬,思考,奋斗,飞翔 181

Vue3 低代码移动表单设计器实战(二):缩放画布下的拖拽系统与树状级联数据结构

本文深入剖析Vue3低代码表单设计器在缩放画布下的拖拽失效问题,揭示SortableJS在CSS Transform下坐标崩溃的数学根源。通过自研独立视觉克隆壳层与逆向几何补偿算法,实现精准拖拽;采用扁平数据存储+运行时树状计算结构,解决级联依赖与深克隆难题,确保逻辑一致性与性能优化,为复杂低代码系统提供可复用的工程范式。

NanChen的博客 349

排序算法深度笔记(上):比较类排序的思想演进与代码实现

与。本文聚焦前者 —— 也就是通过元素间两两比较来确定相对顺序的排序算法,从最朴素的 O (n²) 基础排序,到工业级主流的 O (nlogn) 进阶排序,逐层拆解设计思想、带注释的代码实现与边界细节。当我们理解了比较排序的性能边界,也就自然引出了非比较排序的存在意义。所有代码均遵循统一的实现规范:入口函数前置空数组与单元素边界校验,基于数组原地修改,主函数附带可直接运行的测试用例,与练习代码风格完全对齐。

2401_87069538的博客 634

【计算基础|Redis06】底层数据结构

本文详解Redis 7.4底层数据结构设计:以SDS替代C字符串实现O(1)长度查询与二进制安全;ZSet采用跳表+哈希表组合,兼顾排序与快速查找;小对象用listpack取代ziplist,根除连锁更新问题;List通过quicklist融合紧凑与链表优势;哈希表采用渐进式rehash避免阻塞;整数集合使用intset节省内存。结合OBJECT ENCODING实测,直观展示数据从紧凑编码(int/embstr/listpack)自动切换至通用编码(raw/hashtable)的过程,体现“小则省、大则快

花间相见的博客 339
上一篇: P9497 「RiOI-2」weight
下一篇: P1031 [NOIP 2002 提高组] 均分纸牌
谢天谢地AC了 | 信奥教练
博客等级 码龄1年 53粉丝 177原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值