package main
import (
"bufio"
"fmt"
"os"
)
type Edge struct {
u, v int
}
func main() {
in := bufio.NewReader(os.Stdin)
out := bufio.NewWriter(os.Stdout)
defer out.Flush()
var n int
if _, err := fmt.Fscan(in, &n); err != nil {
return
}
a := make([]int, n+1)
core := make([]int, 0, n)
leaf := make([]int, 0, n)
for i := 1; i <= n; i++ {
fmt.Fscan(in, &a[i])
if a[i] > 1 {
core = append(core, i)
} else {
leaf = append(leaf, i)
}
}
if n == 1 {
fmt.Fprintln(out, "YES 0")
fmt.Fprintln(out, 0)
return
}
if n == 2 {
fmt.Fprintln(out, "YES 1")
fmt.Fprintln(out, 1)
fmt.Fprintln(out, 1, 2)
return
}
if len(core) == 0 {
fmt.Fprintln(out, "NO")
return
}
rem := make([]int, n+1)
copy(rem, a)
edges := make([]Edge, 0, n-1)
for i := 0; i+1 < len(core); i++ {
u, v := core[i], core[i+1]
rem[u]--
rem[v]--
if rem[u] < 0 || rem[v] < 0 {
fmt.Fprintln(out, "NO")
return
}
edges = append(edges, Edge{u, v})
}
diameter := len(core) - 1
if len(leaf) == 1 {
diameter++
} else if len(leaf) >= 2 {
diameter += 2
}
if len(core) == 1 {
c := core[0]
if rem[c] < len(leaf) {
fmt.Fprintln(out, "NO")
return
}
for _, v := range leaf {
edges = append(edges, Edge{c, v})
rem[c]--
}
} else {
idx := 0
if idx < len(leaf) {
u := core[0]
if rem[u] == 0 {
fmt.Fprintln(out, "NO")
return
}
edges = append(edges, Edge{u, leaf[idx]})
rem[u]--
idx++
}
if idx < len(leaf) {
u := core[len(core)-1]
if rem[u] == 0 {
fmt.Fprintln(out, "NO")
return
}
edges = append(edges, Edge{u, leaf[idx]})
rem[u]--
idx++
}
p := 0
for idx < len(leaf) {
for p < len(core) && rem[core[p]] == 0 {
p++
}
if p == len(core) {
fmt.Fprintln(out, "NO")
return
}
u := core[p]
edges = append(edges, Edge{u, leaf[idx]})
rem[u]--
idx++
}
}
if len(edges) != n-1 {
fmt.Fprintln(out, "NO")
return
}
fmt.Fprintf(out, "YES %d\n", diameter)
fmt.Fprintln(out, len(edges))
for _, e := range edges {
fmt.Fprintln(out, e.u, e.v)
}
}