from collections import deque

def count_sort_ind(l, n, i):
    buckets = [[] for j in range(n)]
    for j in range(len(l)):
        buckets[l[j][i]].append(l[j])
    pos = 0
    for j in range(n):
        for val in buckets[j]:
            l[pos] = val
            pos += 1

def kleitman_wang(indeg, outdeg):
    if len(indeg) != len(outdeg):
        return None
    n = len(indeg)
    if sum(indeg) != sum(outdeg):
        return None
    if sum(indeg) == 0:
        return []
    for i in range(n):
        if indeg[i] >= n or indeg[i] < 0:
            return None
        if outdeg[i] >= n or outdeg[i] < 0:
            return None
    # start by getting lexico (bi, ai, i) ord
    to_sort = [(outdeg[i], indeg[i], i) for i in range(n)]
    count_sort_ind(to_sort, n, 1)
    count_sort_ind(to_sort, n, 0)
    # like HH
    count = [deque() for _ in range(n)]
    for i in range(n):
        count[indeg[i]].append(i)
    nxt = [i - 1 for i in range(n + 1)]
    repushed = [False for _ in range(n)]
    edges = []
    count_pos = n - 1
    edges_left = sum(indeg)
    # current maximum lexicographic value (bi, ai), walks down
    cur_lexico = (to_sort[-1][0], to_sort[-1][1])
    # cur_stack has all indices equal to current maximum
    # upcoming stack has those close to it, in a certain sense
    cur_stack, upcoming_stack = [], []
    while edges_left > 0:
        cur = -1
        # This may loop multiple times but is OK amortized
        # first clause activates at most E times
        # second clause either breaks us out or moves a value forward, happens at most E times
        # third clause moves us to next stack, at most E times
        # fourth clause triggers at most V times
        # each loop at least one clause triggers unless we are done
        while cur == -1:
            # If there are more values that are equal to the maximum, fetch them
            while len(to_sort) > 0 and to_sort[-1][0] == cur_lexico[0] and to_sort[-1][1] == cur_lexico[1]:
                cur_stack.append(to_sort[-1][2])
                to_sort.pop()
            # Check the maximums
            while len(cur_stack) > 0:
                maybe_cur = cur_stack[-1]
                cur_stack.pop()
                # if it has not been changed, take it
                if outdeg[maybe_cur] == cur_lexico[0] and indeg[maybe_cur] == cur_lexico[1]:
                    cur = maybe_cur
                    break
                else:
                    # else push it onto the upcoming stack for later
                    upcoming_stack.append(maybe_cur)
                    # if the value is wrong, it was only lowered by 1 each time an edge was added
                    # we will postpone using it at most as often as it was lowered by 1
                    # so we only postpone E times, so amortized this is fine
            if len(cur_stack) == 0 and len(upcoming_stack) > 0:
                # if the upcoming stack is not empty, move to it, max lowers by at least 1
                cur_lexico = (cur_lexico[0], cur_lexico[1] - 1)
                if cur_lexico[1] < 0:
                    cur_lexico = (cur_lexico[0] - 1, n - 1)
                cur_stack, upcoming_stack = upcoming_stack, cur_stack
            # if both are empty we jump down to next value in the order
            if len(cur_stack) == 0 and len(upcoming_stack) == 0 and len(to_sort) > 0:
                cur_lexico = (to_sort[-1][0], to_sort[-1][1])
                cur_stack.append(to_sort[-1][2])
                to_sort.pop()
        # now cur is the index of the current lexicographic maximum (bi, ai)
        # need to change it to (0, ai) and decrease bi values
        # this means it will not be used again, and the ai values are not affected
        # by bi order, so we can just forget it
        # so now we just proceed like in HH
        left = outdeg[cur]
        mov, cut = [], []
        while left > 0:
            while count_pos > 0 and len(count[count_pos]) == 0:
                if len(count[nxt[count_pos]]) == 0:
                    cut.append(count_pos)
                count_pos = nxt[count_pos]
            if count_pos == 0:
                return None
            neigh = count[count_pos][-1]
            count[count_pos].pop()
            while True:
                if not repushed[neigh]:
                    if outdeg[neigh] == 0:
                        repushed[neigh] = True
                        count[count_pos].appendleft(neigh)
                        neigh = count[count_pos][-1]
                        count[count_pos].pop()
                        continue
                break
            if cur != neigh:
                edges.append((cur, neigh))
                left -= 1
                edges_left -= 1
                outdeg[cur] -= 1
                indeg[neigh] -= 1
                if count_pos != 1:
                    mov.append((count_pos - 1, neigh))
            else:
                mov.append((count_pos, neigh))
        for (ind, vert) in mov:
            count[ind].append(vert)
            if nxt[ind + 1] != ind:
                nxt[ind] = nxt[ind + 1]
                nxt[ind + 1] = ind
            count_pos = max(count_pos, ind)
        for ind in cut:
            if len(count[nxt[ind]]) == 0:
                if count_pos == nxt[ind]:
                    count_pos = nxt[nxt[ind]]
                nxt[ind] = nxt[nxt[ind]]
    # sanity check
    assert all(x == 0 for x in indeg)
    assert all(x == 0 for x in outdeg)
    return edges

if __name__ == "__main__":
    n = int(input())
    outdeg = list(map(int, input().strip().split()))
    indeg = list(map(int, input().strip().split()))
    edg = kleitman_wang(indeg, outdeg)
    if edg is None or n == 0:
        print("impossible")
        exit(0)
    rch = [False for _ in range(n)]
    rch[0] = True
    g = [[] for _ in range(n)]
    for a, b in edg:
        g[a].append(b)
        g[b].append(a)
    stk = [0]
    while len(stk) > 0:
        cur = stk[-1]
        stk.pop()
        for x in g[cur]:
            if rch[x]:
                continue
            rch[x] = True
            stk.append(x)
    if sum(rch) != n:
        print("impossible")
    else:
        print(n, len(edg))
        for a, b in edg:
            print(a + 1, b + 1)

