Loading...

【二分】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();
    }
最后更新于 2026-04-05 17:35:33
Code Road Record