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

蓝桥杯[每日一题] 真题:管道(java版)

题目描述

有一根长度为 len 的横向的管道,该管道按照单位长度分为 len 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。一开始管道是空的,位于 Li 的阀门会在 Si 时刻打开,并不断让水流入管道。 对于位于 Li 的阀门,它流入的水在 Ti (Ti ≥ Si) 时刻会使得从第 Li−(Ti−Si) 段到第 Li + (Ti − Si) 段的传感器检测到水流。 求管道中每一段中间的传感器都检测到有水流的最早时间。

输入格式

输入的第一行包含两个整数 n, len,用一个空格分隔,分别表示会打开的阀门数和管道长度。

接下来 n 行每行包含两个整数 Li , Si,用一个空格分隔,表示位于第 Li 段 管道中央的阀门会在 Si 时刻打开。

输出格式

输出一行包含一个整数表示答案。

样例输入

3 10
1 1
6 5
10 2

样例输出

5

评测用例规模 

解题思路

这一道题是典型的二分题目,框架和之前讲的冶炼金属是类似的,但关键就在于check函数怎么写。

在这道题目中,check函数就是一个区间覆盖问题,要判断子区间是否覆盖了原区间。我刚开始想的是,只要前一个的右端点大于等于后一个的左端点,一个一个比,最后能到达末尾就表示覆盖完了区间。这种我感觉不太好写,而且我觉得多多少少有些不对。有人这样写过吗,欢迎在评论区留言!

于是我又去看题解了,发现其实这种思路也挺不错的:按照区间的左端点进行排序,然后一步步拼接区间。有两个关键点:拼不上的情况--上一个区间的右端点加上1还达不到下一个区间的左端点;然后就是能拼上的情况了。但是我写的时候犯了一个错误,我写的判定条件是上一个区间的右端点大于等于下一个区间的左端点。之后画图分析我才发现,如果right是5,下一个区间的左端点是6,这样就会误判为拼不上,但实际是能够拼的。

附上我思考的时候画的图

代码实现 

 


import java.io.*;
import java.util.Arrays;

public class Main {
	private static int n;
	private static int len;

	public static void main(String[] args) throws IOException {
		Scanner scan = new Scanner(System.in);
		n = scan.nextInt();
		len = scan.nextInt();
		int[][] record = new int[n][2];
		int l = 0, r = 1000000010;//为什么取这么大?取太小过不了全部用例
		for (int i = 0; i < n; i++) {
			record[i][0] = scan.nextInt();
			record[i][1] = scan.nextInt();
		}
		while (l < r) {
			int mid = l + r >> 1;
			if (check(mid, record))
				r = mid;
			else
				l = mid + 1;
		}
		System.out.println(l);
	}

	private static boolean check(int T, int[][] record) {
		// 先初始化区间数组
		int[][] temp = new int[record.length][2];
		for (int i = 0; i < record.length; i++) {
			if (T >= record[i][1]) {
				temp[i][0] = record[i][0] - (T - record[i][1]);
				temp[i][1] = record[i][0] + (T - record[i][1]);
			}

		}
		// 合并区间
		Arrays.sort(temp, (x, y) -> Integer.compare(x[0], y[0]));// 按照第一个数排序
		int left = temp[0][0];
		int right = temp[0][1];
		for (int i = 1; i < temp.length; i++) {
			// 接不上
			if (right + 1 < temp[i][0])
				break;
			else
				right = Math.max(right, temp[i][1]);
		}
		return left <= 1 && right >= len;
	}
}


class Scanner {
	private BufferedReader bf;
	private StreamTokenizer st;

	public Scanner(InputStream inputStream) {
		this.bf = new BufferedReader(new InputStreamReader(inputStream));
		this.st = new StreamTokenizer(bf);
	}
	public int nextInt() throws IOException {
		st.nextToken();
		return (int)st.nval;
	}
	public String nextLine() throws IOException {
		return bf.readLine();
	}
}

http://www.dtcms.com/a/98586.html

相关文章:

  • tryhackme——Windows Local Persistence
  • std::reference_wrapper 和 std::function的详细介绍
  • MySQL数据库入门到大蛇尚硅谷宋红康老师笔记 高级篇 part13
  • 【QT】QT样式设计
  • openwrt24.10.0版本上安装istoreOS的屏幕监控插件
  • CentOS 安装 zip
  • 零基础入门多媒体音频(4)-GENIVIProjectAudioManager总览
  • gdb 调试mysql
  • vue3源码分析 -- watch
  • MVC 文件夹:架构之美,开发之魂
  • 从零开始跑通3DGS教程:(三)坐标系与尺度编辑(CloudCompare)
  • HFSS 使用入门
  • 【最后203篇系列】025 FastAPI+Celery
  • AI大模型、机器学习以及AI Agent开源社区和博客
  • 数据结构与算法——顺序表之手撕OJ题
  • 在 Vue 项目中,登录成功后是否存储 token 与用户信息到本地
  • 【NTN 卫星通信】Starlink 星链卫星有多大?详解尺寸与技术参数
  • 深度学习Note.5(机器学习.6)
  • 神经网络检测题
  • FreeRTOS与RT-Thread内存分配对比分析
  • 多线程—JUC(java.util.concurrent)
  • 一个流程图的后续
  • DeepSeek接入飞书多维表格,效率起飞!
  • 【源码阅读/Vue Flask前后端】简历数据查询功能
  • chromem-go + ollama + bge-m3 进行文档向量嵌入和查询
  • 什么是数据集市
  • Redis 源码硬核解析系列专题 - 第二篇:核心数据结构之SDS(Simple Dynamic String)
  • 小程序某点餐平台全自动化实现思路
  • 虚拟现实--->unity学习
  • 动态规划入门:斐波那契模型四题详解(含空间优化技巧)