use std::{cmp::Ordering, collections::BinaryHeap};
fn main() {
assert_eq!(solve(&[1, 100, 10, 10000, 1000]), [0, 2, 1, 4, 3]);
assert_eq!(solve(&[3, 1, 4, 1, 5, 9, 2]), [3, 0, 4, 1, 5, 6, 2]);
assert_eq!(solve(&[0, 1, 0, 1, 0, 1, 0, 1]), [0, 4, 1, 5, 2, 6, 3, 7]);
}
fn solve<T: Ord>(input: &[T]) -> Vec<usize> {
let len = input.len();
let mut heap = (0..len)
.map(|i| BoundIndex(input, i))
.collect::<BinaryHeap<_>>();
let mut output = vec![0; len];
while let Some(bi) = heap.pop() {
output[bi.1] = heap.len();
}
output
}
struct BoundIndex<'a, T: Ord>(&'a [T], usize);
impl<T: Ord> Ord for BoundIndex<'_, T> {
fn cmp(&self, other: &Self) -> Ordering {
(&self.0[self.1], self.1).cmp(&(&other.0[other.1], other.1))
}
}
impl<T: Ord> PartialOrd for BoundIndex<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T: Ord> PartialEq for BoundIndex<'_, T> {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl<T: Ord> Eq for BoundIndex<'_, T> {}
dXNlIHN0ZDo6e2NtcDo6T3JkZXJpbmcsIGNvbGxlY3Rpb25zOjpCaW5hcnlIZWFwfTsKCmZuIG1haW4oKSB7CiAgICBhc3NlcnRfZXEhKHNvbHZlKCZbMSwgMTAwLCAxMCwgMTAwMDAsIDEwMDBdKSwgWzAsIDIsIDEsIDQsIDNdKTsKICAgIGFzc2VydF9lcSEoc29sdmUoJlszLCAxLCA0LCAxLCA1LCA5LCAyXSksIFszLCAwLCA0LCAxLCA1LCA2LCAyXSk7CiAgICBhc3NlcnRfZXEhKHNvbHZlKCZbMCwgMSwgMCwgMSwgMCwgMSwgMCwgMV0pLCBbMCwgNCwgMSwgNSwgMiwgNiwgMywgN10pOwp9CgpmbiBzb2x2ZTxUOiBPcmQ+KGlucHV0OiAmW1RdKSAtPiBWZWM8dXNpemU+IHsKICAgIGxldCBsZW4gPSBpbnB1dC5sZW4oKTsKICAgIGxldCBtdXQgaGVhcCA9ICgwLi5sZW4pCiAgICAgICAgLm1hcCh8aXwgQm91bmRJbmRleChpbnB1dCwgaSkpCiAgICAgICAgLmNvbGxlY3Q6OjxCaW5hcnlIZWFwPF8+PigpOwogICAgbGV0IG11dCBvdXRwdXQgPSB2ZWMhWzA7IGxlbl07CiAgICB3aGlsZSBsZXQgU29tZShiaSkgPSBoZWFwLnBvcCgpIHsKICAgICAgICBvdXRwdXRbYmkuMV0gPSBoZWFwLmxlbigpOwogICAgfQogICAgb3V0cHV0Cn0KCnN0cnVjdCBCb3VuZEluZGV4PCdhLCBUOiBPcmQ+KCYnYSBbVF0sIHVzaXplKTsKCmltcGw8VDogT3JkPiBPcmQgZm9yIEJvdW5kSW5kZXg8J18sIFQ+IHsKICAgIGZuIGNtcCgmc2VsZiwgb3RoZXI6ICZTZWxmKSAtPiBPcmRlcmluZyB7CiAgICAgICAgKCZzZWxmLjBbc2VsZi4xXSwgc2VsZi4xKS5jbXAoJigmb3RoZXIuMFtvdGhlci4xXSwgb3RoZXIuMSkpCiAgICB9Cn0KCmltcGw8VDogT3JkPiBQYXJ0aWFsT3JkIGZvciBCb3VuZEluZGV4PCdfLCBUPiB7CiAgICBmbiBwYXJ0aWFsX2NtcCgmc2VsZiwgb3RoZXI6ICZTZWxmKSAtPiBPcHRpb248T3JkZXJpbmc+IHsKICAgICAgICBTb21lKHNlbGYuY21wKG90aGVyKSkKICAgIH0KfQoKaW1wbDxUOiBPcmQ+IFBhcnRpYWxFcSBmb3IgQm91bmRJbmRleDwnXywgVD4gewogICAgZm4gZXEoJnNlbGYsIG90aGVyOiAmU2VsZikgLT4gYm9vbCB7CiAgICAgICAgc2VsZi5jbXAob3RoZXIpID09IE9yZGVyaW5nOjpFcXVhbAogICAgfQp9CgppbXBsPFQ6IE9yZD4gRXEgZm9yIEJvdW5kSW5kZXg8J18sIFQ+IHt9Cg==