← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
)

type Wizard struct {
	id int
	a  int
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)

	scanner.Scan()
	n, _ := strconv.Atoi(scanner.Text())

	wizards := make([]Wizard, n)
	for i := 0; i < n; i++ {
		scanner.Scan()
		val, _ := strconv.Atoi(scanner.Text())
		wizards[i] = Wizard{id: i, a: val}
	}

	// Separate into Restricted (a > n/2) and Unrestricted
	var restricted []Wizard
	var unrestricted []Wizard
	for _, w := range wizards {
		if w.a > n/2 {
			restricted = append(restricted, w)
		} else {
			unrestricted = append(unrestricted, w)
		}
	}

	// Sort restricted by a descending
	sort.Slice(restricted, func(i, j int) bool {
		return restricted[i].a > restricted[j].a
	})

	ansX := make([]int, n) // stores x-coordinate for wizard i (0-indexed)
	
	// Greedy allocation for x-coordinates
	// Treat a=n as a=n-1 for allocation purposes
	L, R := 1, n
	for _, w := range restricted {
		val := w.a
		effVal := val
		if val == n {
			effVal = n - 1
		}
		
		if L <= n-effVal {
			ansX[w.id] = L
			L++
		} else if R > effVal {
			ansX[w.id] = R
			R--
		} else {
			fmt.Println("NO")
			return
		}
	}

	for _, w := range unrestricted {
		ansX[w.id] = L
		L++
	}

	// Position map: x -> wizard_id
	posToWiz := make([]int, n+1)
	for i := 0; i < n; i++ {
		posToWiz[ansX[i]] = i
	}

	// Try two configurations for y-coordinates to handle a=n
	// Config 1: if a=n and x=1, y=2; else y=1
	// Config 2: if a=n and x=n, y=2; else y=1
	
	configs := []int{1, 2}
	
	finalY := make([]int, n)
	finalTarget := make([]int, n)
	success := false

	for _, cfg := range configs {
		currentY := make([]int, n)
		currentTarget := make([]int, n)
		possible := true

		for i := 0; i < n; i++ {
			if wizards[i].a == n {
				if cfg == 1 && ansX[i] == 1 {
					currentY[i] = 2
				} else if cfg == 2 && ansX[i] == n {
					currentY[i] = 2
				} else {
					currentY[i] = 1
				}
			} else {
				currentY[i] = 1
			}
		}

		for i := 0; i < n; i++ {
			req := wizards[i].a
			x := ansX[i]
			y := currentY[i]
			found := false

			// Check candidates x-req and x+req (if req=n, candidates are outside range usually, 
			// but for a=n we rely on y-diff, so we check x-(n-1) and x+(n-1) logic isn't strictly applicable directly.
			// Actually, we should just check all x that are 'req' distance away in X OR valid candidates.
			// For a=n, x-dist is n-1. For a<n, x-dist is a.
			
			// Candidates based on 1D projection:
			// If a < n, candidate x's are x-a, x+a.
			// If a = n, candidate x's are x-(n-1), x+(n-1) (corners).
			
			distsToCheck := []int{req}
			if req == n {
				distsToCheck = []int{n-1}
			}
			
			for _, d := range distsToCheck {
				cands := []int{x - d, x + d}
				for _, cx := range cands {
					if cx >= 1 && cx <= n {
						targetID := posToWiz[cx]
						ty := currentY[targetID]
						dist := abs(x-cx) + abs(y-ty)
						if dist == req {
							currentTarget[i] = targetID + 1 // 1-based index
							found = true
							break
						}
					}
				}
				if found {
					break
				}
			}
			if !found {
				possible = false
				break
			}
		}

		if possible {
			copy(finalY, currentY)
			copy(finalTarget, currentTarget)
			success = true
			break
		}
	}

	if success {
		fmt.Println("YES")
		for i := 0; i < n; i++ {
			fmt.Printf("%d %d\n", ansX[i], finalY[i])
		}
		for i := 0; i < n; i++ {
			if i > 0 {
				fmt.Print(" ")
			}
			fmt.Print(finalTarget[i])
		}
		fmt.Println()
	} else {
		fmt.Println("NO")
	}
}

func abs(x int) int {
	if x < 0 {
		return -x
	}
	return x
}
```