← Home
```go
package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
)

var scanner *bufio.Scanner

func nextInt() int {
	scanner.Scan()
	v, _ := strconv.Atoi(scanner.Text())
	return v
}

type Point struct {
	X int64
	Y int64
}

func buildUpperHull(pts []Point) []Point {
	var hull []Point
	for _, p := range pts {
		for len(hull) >= 2 {
			p1 := hull[len(hull)-2]
			p2 := hull[len(hull)-1]
			cross := (p2.X-p1.X)*(p.Y-p2.Y) - (p2.Y-p1.Y)*(p.X-p2.X)
			if cross >= 0 {
				hull = hull[:len(hull)-1]
			} else {
				break
			}
		}
		hull = append(hull, p)
	}
	return hull
}

func getMaxF_L(i int, ci int64, UR []Point, n int) float64 {
	low, high := 0, len(UR)-1
	for low < high {
		mid := low + (high-low)/2
		dy1 := UR[mid].Y - ci
		dx1 := UR[mid].X - int64(i)
		dy2 := UR[mid+1].Y - ci
		dx2 := UR[mid+1].X - int64(i)
		if dy1*dx2 <= dy2*dx1 {
			low = mid + 1
		} else {
			high = mid
		}
	}
	bestJ := UR[low]
	M := float64(n-1) / 2.0
	return 2.0 * ((float64(bestJ.X)-M)*float64(ci) + (M-float64(i))*float64(bestJ.Y)) / float64(bestJ.X-int64(i))
}

func getMaxF_R(j int, cj int64, UL []Point, n int) float64 {
	low, high := 0, len(UL)-1
	for low < high {
		mid := low + (high-low)/2
		dy1 := cj - UL[mid].Y
		dx1 := int64(j) - UL[mid].X
		dy2 := cj - UL[mid+1].Y
		dx2 := int64(j) - UL[mid+1].X
		if dy1*dx2 >= dy2*dx1 {
			low = mid + 1
		} else {
			high = mid
		}
	}
	bestI := UL[low]
	M := float64(n-1) / 2.0
	return 2.0 * ((float64(j)-M)*float64(bestI.Y) + (M-float64(bestI.X))*float64(cj)) / float64(int64(j)-bestI.X)
}

type SegTree struct {
	tree []float64
}

func NewSegTree(n int) *SegTree {
	return &SegTree{tree: make([]float64, 4*n)}
}

func (st *SegTree) Update(node, l, r, idx int, val float64) {
	if l == r {
		st.tree[node] = val
		return
	}
	mid := (l + r) / 2
	if idx <= mid {
		st.Update(2*node, l, mid, idx, val)
	} else {
		st.Update(2*node+1, mid+1, r, idx, val)
	}
	st.tree[node] = math.Max(st.tree[2*node], st.tree[2*node+1])
}

func (st *SegTree) Max() float64 {
	if len(st.tree) == 0 {
		return 0
	}
	return st.tree[1]
}

func main() {
	scanner = bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 1024*1024), 10*1024*1024)

	if !scanner.Scan() {
		return
	}
	n, _ := strconv.Atoi(scanner.Text())

	a := make([]int64, n)
	for i := 0; i < n; i++ {
		a[i] = int64(nextInt())
	}

	b := make([]int64, n)
	for i := 0; i < n; i++ {
		b[i] = int64(nextInt())
	}

	M_int := (n - 1) / 2
	var L_end, R_start int
	if (n-1)%2 == 0 {
		L_end = M_int - 1
		R_start = M_int + 1
	} else {
		L_end = M_int
		R_start = M_int + 1
	}

	var ptsR []Point
	for j := R_start; j < n; j++ {
		ptsR = append(ptsR, Point{int64(j), a[j]})
	}
	UR := buildUpperHull(ptsR)

	segL := NewSegTree(L_end + 1)
	for i := 0; i <= L_end; i++ {
		segL.Update(1, 0, L_end, i, getMaxF_L(i, a[i], UR, n))
	}

	c := make([]int64, n)
	copy(c, a)

	var UL []Point
	var segR *SegTree

	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	for k := 0; k < n; k++ {
		c[k] = b[k]

		if k <= L_end {
			segL.Update(1, 0, L_end, k, getMaxF_L(k, c[k], UR, n))
		}

		if k == R_start {
			var ptsL []Point
			for i := 0; i <= L_end; i++ {
				ptsL = append(ptsL, Point{int64(i), c[i]})
			}
			UL = buildUpperHull(ptsL)
			segR = NewSegTree(n - R_start)
			for j := R_start; j < n; j++ {
				segR.Update(1, 0, n-R_start-1, j-R_start, getMaxF_R(j, c[j], UL, n))
			}
		} else if k > R_start {
			segR.Update(1, 0, n-R_start-1, k-R_start, getMaxF_R(k, c[k], UL, n))
		}

		ans := 0.0
		if k < R_start {
			ans = segL.Max()
		} else {
			ans = segR.Max()
		}

		if (n-1)%2 == 0 {
			ans = math.Max(ans, float64(2*c[(n-1)/2]))
		}

		fmt.Fprintf(out, "%.12f ", ans)
	}
	fmt.Fprintln(out)
}
```