// Slower C++ solution:
#include <bits/stdc++.h>



using namespace std;



#define int long long

#define size(x) ((int) x.size())

typedef pair<int,int> pii;



const int MAXN = 1e5 + 5;



int n, root, cnt;

int a[MAXN];

int d[MAXN], sz[MAXN];

int v, par;



vector<int> adj[MAXN];

vector<pii> ans;



pii b[MAXN];



bool cmp(int i, int j) {

	return d[i] > d[j];

}



int getP(int i) {

	int hp = d[i] - n + 2 * sz[i];

	auto tmp = lower_bound(b, b + n, pii(hp, 0)) - b;

	//cerr << b[tmp].first << " " << b[tmp].second << endl;

	if (b[tmp].first != hp) 

		return -1;

	return b[tmp].second;

}



int dfs(int u) {

	int val = 0;

	for (auto v : adj[u])

		val += dfs(v) + sz[v];

	return val;

}

	

int32_t main() {

	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

	cin >> n;

	for (int i = 0; i < n; i++)  {

		cin >> d[i];

		b[i] = {d[i], i};

		a[i] = i;

		sz[i] = 1;

	}

	sort(b, b + n);

	sort(a, a + n, cmp);

	for (int i = 0; i < n - 1; i++) {

		v = a[i];

		par = getP(v);

		//cout << v << " " << par << endl;

		if (par == -1)

			return cout << -1 << endl, 0;

		sz[par] += sz[v];

		ans.push_back({v, par}); 

		adj[par].push_back(v);

		if (2 * sz[v] > n) 

			return cout << -1 << endl, 0;

		//cout << v << " " << par << endl;

	}

	root = a[n - 1];

	if (d[root] != dfs(root))

		return cout << -1 << endl, 0;

	for (auto x : ans) 

		cout << x.first + 1 << " " << x.second + 1 << endl;

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 2.535007208198912x):
#include <bits/stdc++.h>



using namespace std;



const int maxn = 100010;



typedef long long ll;



priority_queue<ll> pq;

map<ll, int> mp;



int n, l[maxn], dep[maxn], sz[maxn], w[maxn], vis[maxn], e_u[maxn], e_v[maxn], tot, e = 0;

ll D[maxn], S[maxn];



struct Edge {

    int v, x;

} E[maxn];



inline void addEdge(int u, int v) {

    E[e].v = v; E[e].x = l[u]; l[u] = e++;

}



void dfs1(int u) {

    sz[u] = 1;

    for (int p = l[u]; p >= 0; p = E[p].x) {

        int v = E[p].v;

        dep[v] = dep[u] + 1;

        dfs1(v);

        sz[u] += sz[v];

    }

}



void dfs2(int u) {

    for (int p = l[u]; p >= 0; p = E[p].x) {

        int v = E[p].v;

        S[v] = S[u] + n - 2 * sz[v];

        dfs2(v);

    }

}



int main() {

    memset(l, -1, sizeof(l));

    scanf("%d", &n);

    for (int i = 1; i <= n; i++) scanf("%lld", &D[i]);

    for (int i = 1; i <= n; i++) {

        mp[D[i]] = i;

        pq.push(D[i]);

        w[i] = 1;

    }

    vis[0] = 1;

    while (pq.size() > 1) {

        ll v = pq.top(); pq.pop();

        int u = mp[v];

        vis[u] = 1;

        if (!vis[mp[v + 2 * w[u] - n]]) {

            int t = mp[v + 2 * w[u] - n];

            w[t] += w[u];

            addEdge(t, u);

            ++ tot;

            e_u[tot] = t; e_v[tot] = u;

        } else {

            puts("-1");

            return 0;

        }

    }

    int r = mp[pq.top()];

    dfs1(r);

    for (int i = 1; i <= n; i++) S[r] += dep[i];

    dfs2(r);

    for (int i = 1; i <= 1; i++) {

        if (S[i] != D[i]) {

            puts("-1");

            return 0;

        }

    }

    for (int i = 1; i <= tot; i++) printf("%d %d\n", e_u[i], e_v[i]);

    return 0;

}