Wilbur is playing with a set of n points on the coordinate plane. All points have non-negative integer coordinates. Moreover, if some point (x, y) belongs to the set, then all points (x', y'), such that 0 ≤ x' ≤ x and 0 ≤ y' ≤ y also belong to this set.

Now Wilbur wants to number the points in the set he has, that is assign them distinct integer numbers from 1 to n. In order to make the numbering aesthetically pleasing, Wilbur imposes the condition that if some point (x, y) gets number i, then all (x',y') from the set, such that x' ≥ x and y' ≥ y must be assigned a number not less than i. For example, for a set of four points (0, 0), (0, 1), (1, 0) and (1, 1), there are two aesthetically pleasing numberings. One is 1, 2, 3, 4 and another one is 1, 3, 2, 4.

Wilbur's friend comes along and challenges Wilbur. For any point he defines it's special value as s(x, y) = y - x. Now he gives Wilbur some w_1, w_2,..., w_{n}, and asks him to find an aesthetically pleasing numbering of the points in the set, such that the point that gets number i has it's special value equal to w_{i}, that is s(x_{i}, y_{i}) = y_{i} - x_{i} = w_{i}.

Now Wilbur asks you to help him with this challenge.


-----Input-----

The first line of the input consists of a single integer n (1 ≤ n ≤ 100 000) — the number of points in the set Wilbur is playing with.

Next follow n lines with points descriptions. Each line contains two integers x and y (0 ≤ x, y ≤ 100 000), that give one point in Wilbur's set. It's guaranteed that all points are distinct. Also, it is guaranteed that if some point (x, y) is present in the input, then all points (x', y'), such that 0 ≤ x' ≤ x and 0 ≤ y' ≤ y, are also present in the input.

The last line of the input contains n integers. The i-th of them is w_{i} ( - 100 000 ≤ w_{i} ≤ 100 000) — the required special value of the point that gets number i in any aesthetically pleasing numbering.


-----Output-----

If there exists an aesthetically pleasant numbering of points in the set, such that s(x_{i}, y_{i}) = y_{i} - x_{i} = w_{i}, then print "YES" on the first line of the output. Otherwise, print "NO".

If a solution exists, proceed output with n lines. On the i-th of these lines print the point of the set that gets number i. If there are multiple solutions, print any of them.


-----Examples-----
Input
5
2 0
0 0
1 0
1 1
0 1
0 -1 -2 1 0

Output
YES
0 0
1 0
2 0
0 1
1 1

Input
3
1 0
0 0
2 0
0 1 2

Output
NO



-----Note-----

In the first sample, point (2, 0) gets number 3, point (0, 0) gets number one, point (1, 0) gets number 2, point (1, 1) gets number 5 and point (0, 1) gets number 4. One can easily check that this numbering is aesthetically pleasing and y_{i} - x_{i} = w_{i}.

In the second sample, the special values of the points in the set are 0,  - 1, and  - 2 while the sequence that the friend gives to Wilbur is 0, 1, 2. Therefore, the answer does not exist.

Difficulty: interview

Starter code:

Solutions:
def __starting_point():

    n = int( input() )

    maxX = [-1]*100005
    for _ in range(n):
        px,py = [int(x) for x in input().split()]
        maxX[py] = max( maxX[py] , px )

    #print( maxX[:2] )

    w = [int(x) for x in input().split()]

    p = [-1]*100005
    p[0] = 0
    wdict = dict()
    wdict[0] = (0,0)
    res = []
    for wi in w:
        if wi in wdict:
            px , py = wdict.pop(wi)
            res.append( (px,py) )
            if maxX[py] > px:
                wdict[py-(px+1)] = (px+1,py)
                p[py] += 1
            if maxX[py+1] != -1 and p[py+1] == -1:
                wdict[py+1] = (0,py+1)
                p[py+1] += 1
        else:
            break

    if len(res) == n:
        print("YES")
        for ares in res:
            print(ares[0],ares[1])
    else:
        print("NO")
__starting_point()

from collections import defaultdict


def solve():
    N = int(input())

    maxx = 0
    maxy = 0
    WS = defaultdict(list)

    for i in range(N):
        x, y = list(map(int, input().split()))
        WS[y - x].append((x, y))
        maxx = max(maxx, x)
        maxy = max(maxy, y)

    for w in WS:
        WS[w].sort(reverse=True)

    W = list(map(int, input().split()))

    ans = [None] * N

    mx = [0] * (maxy + 1)
    my = [0] * (maxx + 1)

    for i in range(N):
        w = W[i]
        if WS[w]:
            ans[i] = ax, ay = WS[w].pop()
            if mx[ay] == ax and my[ax] == ay:
                mx[ay] = ax + 1
                my[ax] = ay + 1

            else:
                print('NO')
                return
        else:
            print('NO')
            return

    print('YES')
    for a in ans:
        print(a[0], a[1])


def __starting_point():
    solve()

__starting_point()

from collections import deque
dp={}
for i in range(int(input())):
	x,y = list(map(int, input().split()))
	if y-x in dp:
		dp[y-x].append((x,y))
	else:
		dp[y-x]=[(x,y)]
for i in dp:
	dp[i].sort()
	dp[i]=deque(dp[i])
w=list(map(int, input().split()))
ans=[0]*len(w)
flag=1
for i in range(len(w)):
	if not w[i] in dp or not len(dp[w[i]]):
		flag=0
		break
	ans[i]=dp[w[i]].popleft()
if not flag:
	print("NO")
else:
	for i in range(1,len(ans)):
		if ans[i][0]<=ans[i-1][0] and ans[i][1]<=ans[i-1][1]:
			flag=0
	if not flag:
		print("NO")
	else:
		print("YES")
		for i in ans:
			print(i[0], i[1])


n = int(input())
MAX = 100000
coord = [list() for i in range(2 * MAX + 1)]
for i in range(n):
    x, y = map(int, input().split())
    coord[y - x - MAX].append((x, y))
w = list(map(int, input().split()))
for i in range(2 * MAX + 1):
    coord[i].sort()
ans = [(0, 0) for i in range(n)]
possible = True
last_x = [-1] * (MAX + 1)
last_y = [-1] * (MAX + 1)
for i in range(n):
    if len(coord[w[i] - MAX]) > 0:
        x = coord[w[i] - MAX][0][0]
        y = coord[w[i] - MAX][0][1]
        if last_x[y] == x - 1 and last_y[x] == y - 1:
            last_x[y] += 1
            last_y[x] += 1
            ans[i] = x, y
            coord[w[i] - MAX].pop(0)
        else:
            possible = False
            break
    else:
        possible = False
        break    
if possible:
    print("YES")
    print("\n".join([" ".join(map(str, coords)) for coords in ans]))
else:
    print("NO")

import collections
import heapq

class SegmentTree(object):
    def __init__(self, size):
        self.capacity = 1 << (len(bin(size - 1)) - 2)
        self.tree = [-1] * self.capacity * 2
        self.tree[0] = size
        self.left = set()
        p = self.capacity
        while p:
            self.left.add(p)
            p >>= 1
        

    def update(self, x, y):
        pos = self.capacity + x
        while pos:
            if y > self.tree[pos]:
                self.tree[pos] = y
            pos >>= 1


    def getmax(self, x):
        pos = self.capacity + x
        y = self.tree[pos]
        while pos:
            if y < self.tree[pos]:
                y = self.tree[pos]
            if pos & 1:
                pos = (pos >> 1) + 1
                if pos in self.left:
                    break
            else:
                pos >>= 1
        return y
    

def read_data():
    n = int(input())
    sxy = collections.defaultdict(list)
    for i in range(n):
        x, y = map(int, input().split())
        heapq.heappush(sxy[y - x], x)
    ws = list(map(int, input().split()))
    return n, sxy, ws

def solve(n, sxy, ws):
    path = []
    for w in ws:
        sxyw = sxy[w]
        if sxyw:
            x = heapq.heappop(sxy[w])
            y = w + x
            path.append((x, y))
        else:
            return False
    if is_valid(path):
        return path
    else:
        return False

def is_valid(path):
    xys = compress(path)
    segtree = SegmentTree(len(xys))
    for x, y in xys:
        maxy = segtree.getmax(x)
        if maxy >= y:
            return False
        segtree.update(x, y)
    return True
        
def compress(path):
    xset = set()
    for x, y in path:
        xset.add(x)
    xuniq = list(xset)
    xuniq.sort()
    dic = {x: i for i, x in enumerate(xuniq)}
    xys = [(dic[x], y) for x, y in path]
    return xys


n, sxy, ws = read_data()
result = solve(n, sxy, ws)
if result:
    print('YES')
    for x, y in result:
        print(x, y)
else:
    print('NO')

n = int(input())

opens = {}
sums = [n - i for i in range(n)] + [0] * (n + 1)
for i in range(n):
    t = tuple(map(int, input().split()))
    opens[t] = 1
    
nums = list(map(int, input().split()))
res = 1
res_nums = []
for elem in nums:
    f = 1
    x = 0
    try:
        x = sums[elem + n]
    except:
        f = 0
    y = x + elem
    
    try:
        u = opens[x, y]
    except KeyError:
        f = 0
    try:
        if opens[x, y - 1] == 1:
            f = 0
    except KeyError:
        pass
    try:
        if opens[x - 1, y] == 1:
            f = 0
    except KeyError:
        pass    
    if f == 0: 
        res = 0
        break
    sums[elem + n] += 1
    opens[x, y] = 0
    res_nums.append((x, y))
    
    
print('YES' if res else 'NO')
if res:
    for elem in res_nums:
        print(str(elem[0]) + ' ' + str(elem[1]))

from bisect import bisect_left

n = int(input())
mas = []
for i in range(n):
	mas.append(0)	
for i in range(n):
	x,y = list(map ( int, input().split()))
	mas[x] = max(mas[x], y)
w = list(map(int, input().split()))
for i in range(n):
	w[i] = -w[i]
s = []
r = []
res1 = []
res2 = []
res3 = []

for i in range(n):
	s.append(i)	
	r.append(i)
	res2.append(-1)
	s[i] -= mas[i] + 1	

error = 0
for i in range(n):
	if error == 1:
		break
	t = bisect_left(r, w[i])
	if ( t >= n or r[t] != w[i] ):
		error = 1
		break
	else:
		r[t] = r[t] - 1
		if ( ( r[t] < s[t] ) or ( t > 0 and r[t] == r[t-1] ) ):
			error = 1    
			break
	res1.append(t)
	res2[t] = res2[t] + 1
	res3.append( res2[t])	

if error == 1:
	print("NO")		
else:
	print("YES")
	for i in range(n):
		print( str(res1[i]) + " " + str(res3[i]))


def main():
    n = int(input())
    diag = [0] * 200005
    use = [0] * 200005
    for i in range(n):
        x, y = [int(i) for i in input().split(' ')]
        c = y - x
        if c > 0:
            diag[c] = max(x+1, diag[c])
        else:
            diag[c] = max(y+1, diag[c])

    table = set()
    for i in range(100005):
        table.add((-1, i))
        table.add((i, -1))

    result = []

    for v in [int(i) for i in input().split(' ')]:
        # print(v)
        if v > 0:
            x = use[v]
            y = x + v
        else:
            y = use[v]
            x = y - v

        # print(x, y, use[v], diag[v], use[v] > diag[v], (x-1, y) not in table, (x, y-1) not in table)

        use[v] += 1

        if use[v] > diag[v]:
            print ('NO')
            return

        if (x-1, y) not in table or (x, y-1) not in table:
            print ('NO')
            return
        table.add((x, y))
        result.append((x, y))

    print('YES')
    for v in result:
        print(v[0], v[1])

main()

from sys import stdin
_data = iter(stdin.read().split('\n'))
input = lambda: next(_data)

n = int(input())
ref, front = {}, {}
ans = []
max_x, max_y = 0, 0
for _ in range(n):
    x, y = list(map(int, input().split()))
    max_x = max(max_x, x)
    max_y = max(max_y, y)    
    ref[(x, y)] = 2
    if x == 0:
        ref[(x, y)] -= 1
    if y == 0:
        ref[(x, y)] -= 1
    if (x, y) == (0, 0):
        del ref[(x, y)]
        front[y - x] = x, y
ws = list(map(int, input().split()))
for w in ws:
    if w not in front:
        ans = []
        break
    x, y = front.pop(w)
    ans.append((x, y))    
    for dx, dy in ((1, 0), (0, 1)):
        nx, ny = x + dx, y + dy
        if (nx, ny) not in ref:
            continue
        ref[(nx, ny)] -= 1
        if ref[(nx, ny)] == 0:
            del ref[(nx, ny)]
            front[ny - nx] = (nx, ny)
if ans:
    print('YES')
    print('\n'.join('{} {}'.format(x, y) for x, y in ans))
else:
    print('NO')


# import sys
# sys.stdin = open('cf596c.in')

from collections import namedtuple, defaultdict, Counter

Point = namedtuple("Point", "x y")

n = int(input())
pts = [Point(*list(map(int, input().split()))) for _ in range(n)]

have = Counter()
for pt in pts:
	have[pt.y - pt.x] += 1

ws = list(map(int, input().split()))
buckets = defaultdict(list)

for i, w in enumerate(ws):
	if have[w] == 0 or (
		(w == 0 and (len(buckets[1]) != len(buckets[0]) or (len(buckets[-1]) != len(buckets[0])))) or
		(w > 0 and ((len(buckets[w + 1]) != len(buckets[w])) or (len(buckets[w - 1]) != len(buckets[w]) + 1))) or
		(w < 0 and ((len(buckets[w - 1]) != len(buckets[w])) or (len(buckets[w + 1]) != len(buckets[w]) + 1)))
		):
		print('NO')
		return
	buckets[w].append(i)
	have[w] -= 1

ans = []
for w, bucket in list(buckets.items()):
	for x, i in enumerate(bucket, max(0, -w)):
		ans.append((Point(x, w + x), i))

ans.sort(key=lambda item: item[1])
print('YES')
print('\n'.join('%d %d' % pt for pt, i in ans))


__author__ = 'mac'

from collections import Counter

def sortByDiag(elem):
        return elem[0]*elem[0]+elem[1]*elem[1]

count = int(input())
points = {}
compList = []
for i in range(count):
    x,y = [int(x) for x in input().strip().split(' ')]
    w = y-x
    compList.append(w)
    if not w in points:
        points[w] = []
    points[w].append([x,y])

wArr = []
for x in input().strip().split(' '):
    if (len(wArr) > 1 and int(x) == wArr[-1]) or (abs(int(x))>len(wArr)):
        print('NO')
        return
    wArr.append(int(x))



c1 = Counter(wArr)
c2 = Counter(compList)

diff = c1-c2
if len(list(diff.elements())) != 0:
     print('NO')
     return

print('YES')

for e in points:
    points[e] = sorted(points[e], key = sortByDiag)

for i in wArr:
    temp = points[i].pop(0)
    print(temp[0],temp[1])

from collections import deque


def ordering(s, ws):
    pbs = {}
    for p in sorted(s):
        pbs.setdefault(p[1]-p[0], deque()).append(p)

    o = []
    os = set()
    for w in ws:
        try:
            p = pbs[w].popleft()
        except (IndexError, KeyError):
            return None

        if ((p[0] > 0 and (p[0]-1, p[1]) not in os)
            or (p[1] > 0 and (p[0], p[1]-1) not in os)):
            return None

        o.append(p)
        os.add(p)


    return o


def pair(x, y):
    return x, y


def __starting_point():
    n = int(input())
    s = {pair(*list(map(int, input().split()))) for _ in range(n)}
    ws = tuple(map(int, input().split()))
    o = ordering(s, ws)
    if o:
        print('YES')
        for p in o:
            print('{} {}'.format(*p))
    else:
        print('NO')

__starting_point()

n = int(input())
R = lambda : list(map(int, input().split()))

p = []
w = {}
r = {}
pr = {}

from collections import deque

for _ in range(n):
    x,y = R()
    p.append((x,y))

p = sorted(p)

for i,wi in enumerate(list(R()),1):
    if wi not in w:
        w[wi] = deque()
    w[wi].append(i)

def solve(p,w,r):
    for i in range(len(p)):
        d = p[i][1]-p[i][0]
        if d in w:
            q = w[d]
            if len(q) > 0:
                ind = q.popleft()
                r[ind] = p[i]
                pr[p[i]] = ind
                if not check_neighbours(p[i],ind,pr):
                    return 0
            else:
                return 0
        else:
            return 0

    return 1

def check_neighbours(p,ind,pr):
    n1 = (p[0]-1,p[1])
    n2 = (p[0],p[1]-1)
    n3 = (p[0]-1,p[1]-1)
    return (check_neighbour(n1,ind,pr) and check_neighbour(n2,ind,pr) and check_neighbour(n3,ind,pr))

def check_neighbour(nb,ind,pr):
    if nb in pr:
        if pr[nb] > ind:
            return 0    
    return 1

if solve(p,w,r) == 0:
    print("NO")
else:
    print("YES")
    for k,v in sorted(r.items()):
        print(v[0], v[1])


from collections import deque

dp={}

for i in range(int(input())):

	x,y = list(map(int, input().split()))

	if y-x in dp:

		dp[y-x].append((x,y))

	else:

		dp[y-x]=[(x,y)]

for i in dp:

	dp[i].sort()

	dp[i]=deque(dp[i])

w=list(map(int, input().split()))

ans=[0]*len(w)

flag=1

for i in range(len(w)):

	if not w[i] in dp or not len(dp[w[i]]):

		flag=0

		break

	ans[i]=dp[w[i]].popleft()

if not flag:

	print("NO")

else:

	for i in range(1,len(ans)):

		if ans[i][0]<=ans[i-1][0] and ans[i][1]<=ans[i-1][1]:

			flag=0

	if not flag:

		print("NO")

	else:

		print("YES")

		for i in ans:

			print(i[0], i[1])





# Made By Mostafa_Khaled


from operator import itemgetter
from collections import defaultdict
n = int(input())
coor = []
coor_list = defaultdict(list)
for _ in range(n):
    x, y = list(map(int,input().split()))
    coor.append((x,y))
    coor_list[y-x].append((x,y))
coor.sort(key=itemgetter(0,1))
order = {cor:i for i, cor in enumerate(coor)}
for x,y in coor_list.items():
    coor_list[x] = sorted(y, key=itemgetter(0,1),reverse=True)


nums = list(map(int, input().split()))
result = []
for i in nums:
    if i not in coor_list:
        print("NO")
        return
    else:
        result.append(coor_list[i].pop())
for i in range(1,n):
    if result[i][0] <= result[i-1][0] and result[i][1] <= result[i-1][1]:
        print("NO")
        return
print("YES")
for i in result:
    print(*i)

import collections

lis = []
n = int(input())
dic = collections.defaultdict(list)
for i in range(n):
    lis.append(tuple(map(int,input().split())))

lis.sort(reverse=True)

for i in range(n):
    dic[lis[i][1]-lis[i][0]].append(lis[i])
lis1 = list(map(int,input().split()))
st = ""
mx1= (-1,-1)
mx2 = (-1,-1)
for i in lis1:
    if dic[i]:
        a = dic[i].pop()
        if (a>= mx1) or a >=mx2:
            
            if mx1[0] < a[0]:
                mx1 = a
            if mx2[1] < a[1]:
                mx2 = a
            
            st+=str(a[0]) + " " + str(a[1])+"\n"
        else:
            print("NO")
            return
    else:
        print("NO")
        return
print("YES")
print(st,end="")
    


from collections import defaultdict
from operator import itemgetter

n = int(input())

points = []
point_weights = defaultdict(list)
for _ in range(n):
    x, y = tuple(map(int,input().split()))
    points.append((x, y))
    point_weights[y - x].append((x, y))

weights = list(map(int, input().split()))

points.sort(key=itemgetter(0, 1))

for w, p in list(point_weights.items()):
    point_weights[w] = sorted(p, key=itemgetter(0, 1), reverse=True)

ans = "YES"
ans_arr = []
for weight in weights:
    if weight not in point_weights:
        ans = "NO"
        break
    else:
        if len(point_weights[weight]) == 0:
            ans = "NO"
            break
        else:
            ans_arr.append(point_weights[weight].pop())

for i in range(1, len(ans_arr)):
    if ans_arr[i][0] <= ans_arr[i - 1][0] and ans_arr[i][1] <= ans_arr[i - 1][1]:
        ans = "NO"
        break

print(ans)
if ans == "YES":
    for point in ans_arr:
        print(*point)


from itertools import combinations,permutations
from collections import defaultdict

def zeror():
    return 0

def solution(n,c,cw,w):

    c.sort(key=lambda tup:tup[0])
    #print(c)

    for k,v in cw.items():
        cw[k]=sorted(v,key=lambda tup:tup[0])[::-1]

    #print(cw)

    ans=[]

    for elem in w:
        if elem not in cw:
            print("NO")
            return
        else:
            ans.append(cw[elem].pop())

    #print(ans)
    temp=ans[0]
    for elem in ans[1:]:
        if temp[0]>=elem[0] and temp[1]>=elem[1]:
            print("NO")
            return
        temp=elem

    print("YES")
    for elem in ans:
        print(elem[0],elem[1])




def main():
    n=int(input())
    coordinates = []
    coor_weights = defaultdict(list)
    for _ in range(n):
        coordinates.append(tuple(map(int,input().strip().split())))
        coor_weights[coordinates[-1][1]-coordinates[-1][0]].append((coordinates[-1][0],coordinates[-1][1]))
    weigths=list(map(int,input().strip().split()))

    solution(n,coordinates,coor_weights,weigths)



def __starting_point():
    main()


"""

5
2 0
0 0
1 0
1 1
0 1
0 -1 -2 1 


"""
__starting_point()

n = int(input().rstrip())
l = set()
for i in range(n):
    l.add(tuple(map(int, input().rstrip().split())))

w = list(map(int, input().rstrip().split()))

d = {0: (0, 0)}
s = ""
visited = set()
visited.add((0, 0))
for k in w:
    if d.get(k, None) is None:
        print("NO")
        return

    p = d[k]
    del d[k]
    s += "{} {}\n".format(*p)
    if p[1] == 0 and (p[0] + 1, p[1]) in l:
        visited.add((p[0] + 1, p[1]))
        d[-p[0] - 1] = (p[0] + 1, 0)
    else:
        if (p[0] + 1, p[1] - 1) in visited and (p[0]+1, p[1]) in l:
            visited.add((p[0] + 1, p[1]))
            d[p[1] - p[0] - 1] = (p[0] + 1, p[1])
    if p[0] == 0 and (0, p[1] + 1) in l:
        d[p[1] + 1] = (0, p[1] + 1)
        visited.add((0, p[1] + 1))
    else:
        if (p[0] - 1, p[1] + 1) in visited and (p[0], p[1] + 1) in l:
            visited.add((p[0], p[1] + 1))
            d[p[1]-p[0] + 1] = (p[0], p[1] + 1)

print("YES")
print(s,end="")

     	 		 		   	   	  		 	  	 	

def binsearch(lofpoints,l,r,w,arr):
    if(l>r):
        return "None"
    mid=(l+r)//2
    if(lofpoints[mid][0]==w and arr[mid]==1):
        if(mid==0):
            arr[mid]=0
            return mid
        elif(lofpoints[mid-1][0]!=w or arr[mid-1]==0):
            arr[mid]=0
            return mid
        else:
            return binsearch(lofpoints,l,mid-1,w,arr)
    if(lofpoints[mid][0]==w and arr[mid]==0):
        return binsearch(lofpoints,mid+1,r,w,arr)
    if(lofpoints[mid][0]<w):
        return binsearch(lofpoints,mid+1,r,w,arr)
    if(lofpoints[mid][0]>w):
        return binsearch(lofpoints,l,mid-1,w,arr)


n=int(input())
lofpoints=[]
for i in range(n):
    l=input().split()
    x=int(l[0])
    y=int(l[1])
    lofpoints.append((y-x,x,y))
lofpoints.sort()
w=input().split()
wi=[int(i) for i in w]
arr=[1 for i in range(n)]
lsol=[]
done=1
#print(lofpoints)
for i in range(n):
    x=binsearch(lofpoints,0,n-1,wi[i],arr)
    #print(x)
    if(x=="None"):
        done=0
        break
    elif(lsol==[]):
        lsol.append((lofpoints[x][1],lofpoints[x][2]))

    elif(lofpoints[x][1]<lsol[-1][0] and lofpoints[x][2]<lsol[-1][1]):
        done=0
        break
    else:
        lsol.append((lofpoints[x][1],lofpoints[x][2]))
#print(lsol)
if(done==1):
    hashi=dict()
    for i in range(n):
        hashi[(lsol[i][0],lsol[i][1])]=i
    for i in hashi:
        x=i[0]
        y=i[1]
        t=hashi[i]
        if((x,y+1) in hashi):
            if(hashi[(x,y+1)]<t):
                done=0
                break
        if((x+1,y) in hashi):
            if(hashi[(x+1,y)]<t):
                done=0
                break

    if(done==0):
        print("NO")
    else:
        print("YES")
        for i in lsol:
            print(i[0],i[1])
else:
    print("NO")


n = int(input())
p = sorted([tuple(map(int, input().split())) for _ in range(n)])
arr = list(map(int, input().split()))
w, r, pr = {}, {}, {}

for i, wi in enumerate(arr, 1):
    if wi not in w:
        w[wi] = []
    w[wi].append(i)
 
def is_nbr(nb, i):
    return 0 if pr.get(nb, 0) > i else 1

def check_nbrs(p, i):
    n1 = (p[0] - 1, p[1])
    n2 = (p[0], p[1] - 1)
    n3 = (p[0] - 1, p[1] - 1)
    return is_nbr(n1, i) and is_nbr(n2, i) and is_nbr(n3, i)

def solve():
    for i in range(len(p)):
        d = p[i][1] - p[i][0]
        if d not in w:
            return 0
        q = w[d]
        if not q:
            return 0
        ind = q.pop(0)
        r[ind] = p[i]
        pr[p[i]] = ind
        if not check_nbrs(p[i], ind):
            return 0
    return 1
 
if solve() == 0:
    print("NO")
else:
    print("YES")
    for k, v in sorted(r.items()):
        print(v[0], v[1])