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

蓝桥杯[每日一题] 真题:管道(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.kler.cn/a/614156.html

相关文章:

  • 基于飞腾FT2000/4的全国产标准6U VPX板卡,支持银河麒麟
  • 1500 字节 MTU | 溯源 / 技术权衡 / 应用影响
  • 知识图谱初相识(概念理解篇)
  • Zookeeper特性与节点数据类型
  • 告别桌面杂乱与充电焦虑,移速165W百变桌面充电站首发体验
  • TDengine 中的异常恢复
  • vue搭建一个树形菜单项目
  • std::countr_zero
  • 如何让AI套用现有ppt模板,并通过改文字批量生成新的ppt?【翻车版】
  • 【动态规划篇】- 路径问题
  • uniapp用法--uni.navigateTo 使用与参数携带的方式示例(包含复杂类型参数)
  • 【AI知识】深度学习中模型参数初始化方法介绍
  • 【Hugging Face 开源库】Diffusers 库 —— 扩散模型
  • 【STM32】知识点介绍二:GPIO引脚介绍
  • Markdown 和 Microsoft Word对比
  • C++细节知识for面试
  • 【老电脑翻新】华硕A456U(换电池+换固态+光驱换机械+重装系统+重装系统后开始菜单失灵问题解决)
  • 【附代码】【MILP建模】3D装箱问题(3D-Bin Packing Problem)
  • LVS的 NAT 模式实验
  • QT:信号映射器