题意

平面上有n个点,每个点有一个点权v。你现在可以以原点为圆心放置一个圆,请问要使圆能覆盖到的点的权值和达到x,圆的半径至少为多少?

思路

最小值问题 先考虑下单调性

点的点权为正整数,如果圆的半径增加,那么能覆盖的点会增大,权值和增大,具有单调性,所以可以二分圆的半径。

对于check函数,需要判断在圆里的点的权值和。这里用的是点到原点的距离和半径的比较做的

Go代码

package main

import "fmt"

type MyPoint struct {
	x, y, v int64
}

func main() {
	var n int
	var x int64
	fmt.Scan(&n, &x)
	points := make([]MyPoint, n+1)
	for i := 1; i <= n; i++ {
		fmt.Scan(&points[i].x, &points[i].y, &points[i].v)
	}
	var l, r, ans float64 = 0, 1e10, -1
	const AUC = 0.000_001
	check := func(r float64) bool {
		var sum int64 = 0
		for i := 1; i <= n; i++ {
			var tmp int64 = points[i].x * points[i].x + points[i].y * points[i].y
			if float64(tmp) <= r * r {
				sum += points[i].v
			}
		}
		return sum >= x
	}
	for l <= r {
		mid := (l + r) / 2
		if check(mid) {
			ans = mid
			r = mid - AUC
		} else {
			l = mid + AUC
		}
	}
	fmt.Println(ans)
}