// Copyright (c) 2016 Kiel University and others.
//
// This program and the accompanying materials are made available under the
// terms of the Eclipse Public License 2.0 which is available at
// https://www.eclipse.org/legal/epl-2.0.
//
// SPDX-License-Identifier: EPL-2.0

package p3order

// binaryIndexedTree is ELK 0.8.1's sorted integer multiset. It stores values
// in [0,maxNum) and supports insertion, exclusive rank, and bulk removal in
// O(log maxNum). Keeping the two backing arrays is intentional: removeAll
// needs the multiplicity at one leaf while binarySums is a Fenwick tree.
type binaryIndexedTree struct {
	binarySums   []int
	numsPerIndex []int
	size         int
	maxNum       int
}

func newBinaryIndexedTree( int) *binaryIndexedTree {
	if  < 0 {
		panic("p3order: negative binary indexed tree size")
	}
	return &binaryIndexedTree{
		binarySums:   make([]int, +1),
		numsPerIndex: make([]int, ),
		maxNum:       ,
	}
}

func ( *binaryIndexedTree) ( int) {
	if  < 0 ||  >= .maxNum {
		panic("p3order: binary indexed tree index out of range")
	}
	.size++
	.numsPerIndex[]++
	for  :=  + 1;  < len(.binarySums);  +=  & - {
		.binarySums[]++
	}
}

// rank returns the number of stored values strictly before index.
func ( *binaryIndexedTree) ( int) int {
	if  < 0 ||  > .maxNum {
		panic("p3order: binary indexed tree rank index out of range")
	}
	 := 0
	for  := ;  > 0;  -=  & - {
		 += .binarySums[]
	}
	return 
}

func ( *binaryIndexedTree) ( int) {
	if  < 0 ||  >= .maxNum {
		panic("p3order: binary indexed tree index out of range")
	}
	 := .numsPerIndex[]
	if  == 0 {
		return
	}
	.numsPerIndex[] = 0
	.size -= 
	for  :=  + 1;  < len(.binarySums);  +=  & - {
		.binarySums[] -= 
	}
}

func ( *binaryIndexedTree) () {
	.binarySums = make([]int, .maxNum+1)
	.numsPerIndex = make([]int, .maxNum)
	.size = 0
}

func ( *binaryIndexedTree) () bool { return .size == 0 }