← Home
package main

import (
	"bufio"
	"fmt"
	"os"
)

type SegTree struct {
	maxVal []int
	minVal []int
	lazy   []int
	size   int
}

func NewSegTree(n int, initVals []int) *SegTree {
	size := 1
	for size <= n {
		size *= 2
	}
	st := &SegTree{
		maxVal: make([]int, 2*size),
		minVal: make([]int, 2*size),
		lazy:   make([]int, 2*size),
		size:   size,
	}
	st.build(1, 0, size-1, initVals)
	return st
}

func (st *SegTree) build(node, l, r int, initVals []int) {
	if l == r {
		if l < len(initVals) {
			st.maxVal[node] = initVals[l]
			st.minVal[node] = initVals[l]
		}
		return
	}
	mid := (l + r) / 2
	st.build(node*2, l, mid, initVals)
	st.build(node*2+1, mid+1, r, initVals)
	st.maxVal[node] = max(st.maxVal[node*2], st.maxVal[node*2+1])
	st.minVal[node] = min(st.minVal[node*2], st.minVal[node*2+1])
}

func (st *SegTree) push(node int) {
	if st.lazy[node] != 0 {
		lz := st.lazy[node]
		st.maxVal[node*2] += lz
		st.minVal[node*2] += lz
		st.lazy[node*2] += lz
		st.maxVal[node*2+1] += lz
		st.minVal[node*2+1] += lz
		st.lazy[node*2+1] += lz
		st.lazy[node] = 0
	}
}

func (st *SegTree) Update(ql, qr, val int) {
	st.update(1, 0, st.size-1, ql, qr, val)
}

func (st *SegTree) update(node, l, r, ql, qr, val int) {
	if ql <= l && r <= qr {
		st.maxVal[node] += val
		st.minVal[node] += val
		st.lazy[node] += val
		return
	}
	st.push(node)
	mid := (l + r) / 2
	if ql <= mid {
		st.update(node*2, l, mid, ql, qr, val)
	}
	if qr > mid {
		st.update(node*2+1, mid+1, r, ql, qr, val)
	}
	st.maxVal[node] = max(st.maxVal[node*2], st.maxVal[node*2+1])
	st.minVal[node] = min(st.minVal[node*2], st.minVal[node*2+1])
}

func (st *SegTree) QueryMax(ql, qr int) int {
	return st.queryMax(1, 0, st.size-1, ql, qr)
}

func (st *SegTree) queryMax(node, l, r, ql, qr int) int {
	if ql <= l && r <= qr {
		return st.maxVal[node]
	}
	st.push(node)
	mid := (l + r) / 2
	res := -int(1e9)
	if ql <= mid {
		res = max(res, st.queryMax(node*2, l, mid, ql, qr))
	}
	if qr > mid {
		res = max(res, st.queryMax(node*2+1, mid+1, r, ql, qr))
	}
	return res
}

func (st *SegTree) QueryMin(ql, qr int) int {
	return st.queryMin(1, 0, st.size-1, ql, qr)
}

func (st *SegTree) queryMin(node, l, r, ql, qr int) int {
	if ql <= l && r <= qr {
		return st.minVal[node]
	}
	st.push(node)
	mid := (l + r) / 2
	res := int(1e9)
	if ql <= mid {
		res = min(res, st.queryMin(node*2, l, mid, ql, qr))
	}
	if qr > mid {
		res = min(res, st.queryMin(node*2+1, mid+1, r, ql, qr))
	}
	return res
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	var n int
	fmt.Fscan(reader, &n)

	a := make([]int, n+1)
	pos := make([][]int, n+1)
	for i := 1; i <= n; i++ {
		fmt.Fscan(reader, &a[i])
		pos[a[i]] = append(pos[a[i]], i)
	}

	initVals := make([]int, n+1)
	for i := 0; i <= n; i++ {
		initVals[i] = -i
	}

	st := NewSegTree(n+1, initVals)
	ans := make([]int, n+1)

	for x := 1; x <= n; x++ {
		for _, i := range pos[x] {
			maxQ := st.QueryMax(0, i-1)
			minQ := st.QueryMin(i, n)
			v2 := maxQ - minQ
			ans[i] = max(ans[i], v2/2)
		}

		for _, i := range pos[x] {
			st.Update(i, n, 2)
		}

		for _, i := range pos[x] {
			maxP := st.QueryMax(i, n)
			minP := st.QueryMin(0, i-1)
			v1 := maxP - minP
			ans[i] = max(ans[i], (v1-1)/2)
		}
	}

	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()
	for i := 1; i <= n; i++ {
		if i > 1 {
			fmt.Fprint(writer, " ")
		}
		fmt.Fprint(writer, ans[i])
	}
	fmt.Fprintln(writer)
}