← Home
For problem statement at 0-999/800-899/880-889/887/problemE.txt this is a correct solution, but verifier at 0-999/800-899/880-889/887/verifierE.go ends with All tests passed can you fix the verifier? package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"math/bits"
	"os"
	"sort"
)

type Interval struct {
	l, r float64
}

type U128 struct {
	hi, lo uint64
}

func mul64U(a, b uint64) U128 {
	hi, lo := bits.Mul64(a, b)
	return U128{hi: hi, lo: lo}
}

func addU(a, b U128) U128 {
	lo, c := bits.Add64(a.lo, b.lo, 0)
	hi, _ := bits.Add64(a.hi, b.hi, c)
	return U128{hi: hi, lo: lo}
}

func subU(a, b U128) U128 {
	lo, c := bits.Sub64(a.lo, b.lo, 0)
	hi, _ := bits.Sub64(a.hi, b.hi, c)
	return U128{hi: hi, lo: lo}
}

func cmpU(a, b U128) int {
	if a.hi < b.hi {
		return -1
	}
	if a.hi > b.hi {
		return 1
	}
	if a.lo < b.lo {
		return -1
	}
	if a.lo > b.lo {
		return 1
	}
	return 0
}

func lshiftU(a U128, k uint) U128 {
	if k == 0 {
		return a
	}
	if k < 64 {
		return U128{
			hi: a.hi<<k | a.lo>>(64-k),
			lo: a.lo << k,
		}
	}
	if k == 64 {
		return U128{hi: a.lo, lo: 0}
	}
	return U128{hi: a.lo << (k - 64), lo: 0}
}

func u128ToFloat(a U128) float64 {
	return math.Ldexp(float64(a.hi), 64) + float64(a.lo)
}

func diffToFloat(a, b U128) float64 {
	c := cmpU(a, b)
	if c >= 0 {
		return u128ToFloat(subU(a, b))
	}
	return -u128ToFloat(subU(b, a))
}

func absU64(x int64) uint64 {
	if x < 0 {
		return uint64(-x)
	}
	return uint64(x)
}

func signedMulToFloat(a, b int64) float64 {
	v := u128ToFloat(mul64U(absU64(a), absU64(b)))
	if (a < 0) != (b < 0) {
		return -v
	}
	return v
}

func scanSide(arr []Interval) float64 {
	if len(arr) == 0 {
		return 0
	}
	sort.Slice(arr, func(i, j int) bool {
		if arr[i].l == arr[j].l {
			return arr[i].r < arr[j].r
		}
		return arr[i].l < arr[j].l
	})
	x := 0.0
	for _, in := range arr {
		if in.l >= x {
			break
		}
		if in.r <= x {
			continue
		}
		x = in.r
	}
	return x
}

type FastScanner struct {
	data []byte
	idx  int
	n    int
}

func NewFastScanner() *FastScanner {
	data, _ := io.ReadAll(os.Stdin)
	return &FastScanner{data: data, n: len(data)}
}

func (fs *FastScanner) NextInt64() int64 {
	for fs.idx < fs.n {
		c := fs.data[fs.idx]
		if c == '-' || (c >= '0' && c <= '9') {
			break
		}
		fs.idx++
	}
	sign := int64(1)
	if fs.data[fs.idx] == '-' {
		sign = -1
		fs.idx++
	}
	var v int64
	for fs.idx < fs.n {
		c := fs.data[fs.idx]
		if c < '0' || c > '9' {
			break
		}
		v = v*10 + int64(c-'0')
		fs.idx++
	}
	return sign * v
}

func main() {
	fs := NewFastScanner()

	x1 := fs.NextInt64()
	y1 := fs.NextInt64()
	x2 := fs.NextInt64()
	y2 := fs.NextInt64()
	n := int(fs.NextInt64())

	dx := x2 - x1
	dy := y2 - y1
	D := dx*dx + dy*dy
	sqrtD := math.Sqrt(float64(D))

	intervals := make([]Interval, 0, n)

	for i := 0; i < n; i++ {
		cx := fs.NextInt64()
		cy := fs.NextInt64()
		r := fs.NextInt64()

		cross := dx*(cy-y1) - dy*(cx-x1)

		mdx := 2*cx - x1 - x2
		mdy := 2*cy - y1 - y2
		z := mdx*mdx + mdy*mdy - D - 4*r*r

		rr := uint64(r * r)
		rrD := mul64U(rr, uint64(D))

		cross2 := mul64U(absU64(cross), absU64(cross))
		N := subU(cross2, rrD)
		Nf := u128ToFloat(N)

		alpha := 4.0 * Nf
		beta := -signedMulToFloat(z, cross)

		z2 := mul64U(absU64(z), absU64(z))
		z2f := u128ToFloat(z2)

		Gf := diffToFloat(z2, lshiftU(rrD, 4)) / 16.0

		sqrtDisc := float64(r) * sqrtD * math.Sqrt(z2f+16.0*Nf)

		qv := -0.5 * (beta + math.Copysign(sqrtDisc, beta))
		s1 := qv / alpha
		s2 := Gf / qv
		if s1 > s2 {
			s1, s2 = s2, s1
		}
		intervals = append(intervals, Interval{l: s1, r: s2})
	}

	right := scanSide(intervals)

	for i := range intervals {
		intervals[i] = Interval{l: -intervals[i].r, r: -intervals[i].l}
	}

	left := scanSide(intervals)

	best := right
	if left < best {
		best = left
	}

	ans := sqrtD * math.Sqrt(0.25+best*best)

	w := bufio.NewWriterSize(os.Stdout, 1<<20)
	fmt.Fprintf(w, "%.15f\n", ans)
	w.Flush()
}