算法 【二分】BISHI86 圆覆盖 思路 求解代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 /** * 表示一个点的静态内部类 * 包含两个属性:d2和v */ static class Point { // 平方距离属性,通常用于表示点与点之间的距离平方 long d2; // 权值属性 long v; Point(long d2, long v) { // 使用this关键字将参数值赋给类的成员变量 this.d2 = d2; this.v = v; } } public static void main(String[] args) throws IOException { // 使用BufferedReader读取输入,使用PrintWriter输出结果 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out)); // 读取第一行输入,分割为字符串数组 String[] strA = br.readLine().trim().split("\\s+"); // 获取点的数量n int n = Integer.parseInt(strA[0]); // 获取所需的最小权值S long S = Long.parseLong(strA[1]); // 创建二维数组存储每个点的坐标和权值 long[][] a = new long[n][3]; // 创建Point数组,用于存储每个点到原点的距离平方和权值 Point[] points = new Point[n]; // 初始化总权值 long total = 0; // 读取每个点的数据并计算相关信息 for (int i = 0; i < n; i++) { // 读取一行输入并分割 String[] str = br.readLine().trim().split("\\s+"); // 存储x坐标 a[i][0] = Long.parseLong(str[0]); // 存储y坐标 a[i][1] = Long.parseLong(str[1]); // 存储权值 a[i][2] = Long.parseLong(str[2]); // 创建Point对象,计算点到原点的距离平方 points[i] = new Point(a[i][0] * a[i][0] + a[i][1] * a[i][1], a[i][2]); // 累加总权值 total += a[i][2]; } // 如果总权值小于所需权值S,输出-1并返回 if (total < S) { out.println("-1"); out.flush(); return; } // 对points数组进行排序,使用Lambda表达式作为比较器,按照d2属性值升序排序 Arrays.sort(points, (x1, x2) -> Long.compare(x1.d2, x2.d2)); // 创建前缀和数组preSum,长度为n long[] preSum = new long[n]; // 初始化前缀和数组的第一个元素为points[0]的v值 preSum[0] = points[0].v; // 计算前缀和数组,preSum[i]存储从points[0]到points[i]的v值之和 for (int i = 1; i < n; i++) { preSum[i] = preSum[i - 1] + points[i].v; } // 初始化二分查找的边界,low为0,high为n-1 int low = 0, high = n - 1; // 初始化index为n-1,用于存储满足条件的最小索引 int index = n - 1; // 使用二分查找算法找到满足preSum[mid] >= S的最小mid值 while (low <= high) { // 计算中间位置,使用位运算防止溢出 int mid = low + ((high - low) >> 1); // 如果当前前缀和大于等于S,则更新index并向左查找更小的值 if (preSum[mid] >= S) { index = mid; high = mid - 1; } else { // 否则向右查找 low = mid + 1; } } // 输出满足条件的点的d2值的平方根 out.println(Math.sqrt(points[index].d2)); // 刷新输出流 out.flush(); // 关闭输出流 out.close(); // 关闭输入流 br.close(); }