#include <bits/stdc++.h>
using namespace std;
using ll = long long;

map<int, set<int>> existing;
vector<int> results;
vector<int> depths;
vector<bool> used;

void build(int l, int r, int d) {
	if (r - l == 1) {
		depths[l] = d;
		existing[d].insert(l);
		return;
	}
	int m = (l + r) / 2;
	build(l, m, d+1);
	build(m, r, d+1);
}

void propagate(int l, int r, int d) {
	if (r - l == 1) {
		existing[depths[l]].erase(l);
		depths[l] = d;
		existing[d].insert(l);
		return;
	}
	int m = (l + r) / 2;
	propagate(l, m, d+1);
	propagate(m, r, d+1);
}

void fill(int v, int l, int r, int d, int i) {
	if (r - l == 1) {
		existing[depths[l]].erase(l);
		return;
	}
	int m = (l + r) / 2;
	if (i < m) fill(2*v+1, l, m, d+1, i);
	else fill(2*v+2, m, r, d+1, i);
	if (!used[v]) {
		used[v] = true;
		if (i < m) propagate(m, r, 1);
		else propagate(l, m, 1);
	}
}

int main() {
	int tree_size;
	cin >> tree_size;
	int n = tree_size / 2 + 1;
	results.resize(n);
	depths.resize(n);
	used.resize(tree_size, false);
	vector<int> compressing(tree_size);
	for (int &i: compressing) {
		cin >> i;
	}
	vector<int> starting = compressing;
	sort(compressing.begin(), compressing.end());
	compressing.resize(unique(compressing.begin(), compressing.end()) - compressing.begin());
	vector<int> amounts(compressing.size());
	for (int i: starting) {
		amounts[lower_bound(compressing.begin(), compressing.end(), i) - compressing.begin()] += 1;
	}
	build(0, n, 1);
	bool answer_exists = true;
	for (int i = 0; i < (int)compressing.size(); i++) {
		auto cur_bucket = existing.find(amounts[i]);
		if (cur_bucket == existing.end() || cur_bucket->second.empty()) {
			cout << -1 << "\n";
			answer_exists = false;
			break;
		}
		else {
			int v = *(cur_bucket->second.begin());
			results[v] = i;
			fill(0, 0, n, 0, v);
		}
	}
	if (answer_exists) {
		for (int i: results) {
			cout << compressing[i] << " ";
		}
	}
}