118 lines
2 KiB
Go
118 lines
2 KiB
Go
package q3510
|
|
|
|
import "container/heap"
|
|
|
|
type Node struct {
|
|
val int
|
|
prev, next *Node
|
|
arrPos, heapPos int
|
|
}
|
|
|
|
type MinAdjSum []*Node
|
|
|
|
func (m *MinAdjSum) Len() int { return len(*m) }
|
|
|
|
func (m *MinAdjSum) Less(i int, j int) bool {
|
|
if (*m)[i].next == nil {
|
|
return false
|
|
}
|
|
if (*m)[j].next == nil {
|
|
return true
|
|
}
|
|
s1, p1 := (*m)[i].val+(*m)[i].next.val, (*m)[i].arrPos
|
|
s2, p2 := (*m)[j].val+(*m)[j].next.val, (*m)[j].arrPos
|
|
if s1 == s2 {
|
|
return p1 < p2
|
|
}
|
|
return s1 < s2
|
|
}
|
|
|
|
func (m *MinAdjSum) Push(x any) {
|
|
elem := x.(*Node)
|
|
elem.heapPos = len(*m)
|
|
*m = append(*m, elem)
|
|
}
|
|
|
|
func (m *MinAdjSum) Pop() any {
|
|
ret := (*m)[len(*m)-1]
|
|
(*m) = (*m)[:len(*m)-1]
|
|
return ret
|
|
}
|
|
|
|
func (m *MinAdjSum) Swap(i int, j int) {
|
|
(*m)[i].heapPos = j
|
|
(*m)[j].heapPos = i
|
|
(*m)[i], (*m)[j] = (*m)[j], (*m)[i]
|
|
}
|
|
|
|
func minimumPairRemoval(nums []int) int {
|
|
outOfOrder := 0
|
|
for i := range len(nums) - 1 {
|
|
if nums[i] > nums[i+1] {
|
|
outOfOrder++
|
|
}
|
|
}
|
|
if outOfOrder == 0 {
|
|
return 0
|
|
}
|
|
|
|
nodes := make([]Node, len(nums))
|
|
hp := make(MinAdjSum, len(nums))
|
|
for i := range nums {
|
|
nodes[i] = Node{val: nums[i], heapPos: i, arrPos: i}
|
|
hp[i] = &nodes[i]
|
|
|
|
if i > 0 {
|
|
nodes[i].prev = &nodes[i-1]
|
|
}
|
|
if i+1 < len(nums) {
|
|
nodes[i].next = &nodes[i+1]
|
|
}
|
|
}
|
|
heap.Init(&hp)
|
|
|
|
ops := 0
|
|
for ; outOfOrder > 0; ops++ {
|
|
node := hp[0]
|
|
next, prev := node.next, node.prev
|
|
|
|
heap.Remove(&hp, node.heapPos)
|
|
heap.Remove(&hp, next.heapPos)
|
|
if prev != nil {
|
|
heap.Remove(&hp, prev.heapPos)
|
|
}
|
|
|
|
// Update outOfOrder
|
|
if next.val < node.val {
|
|
outOfOrder--
|
|
}
|
|
if next.next != nil && next.next.val < next.val {
|
|
outOfOrder--
|
|
}
|
|
if prev != nil && node.val < prev.val {
|
|
outOfOrder--
|
|
}
|
|
|
|
node.val += next.val
|
|
if prev != nil && node.val < prev.val {
|
|
outOfOrder++
|
|
}
|
|
if next.next != nil && next.next.val < node.val {
|
|
outOfOrder++
|
|
}
|
|
|
|
// Update links & fix heap
|
|
node.next = next.next
|
|
if next.next != nil {
|
|
next.next.prev = node
|
|
}
|
|
|
|
heap.Push(&hp, node)
|
|
if prev != nil {
|
|
heap.Push(&hp, prev)
|
|
}
|
|
}
|
|
return ops
|
|
}
|
|
|
|
var _ = minimumPairRemoval
|