← Home
```go
package main

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

type Point struct {
	x, y int
}

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

	readInt := func() int {
		scanner.Scan()
		s := scanner.Bytes()
		v := 0
		for _, c := range s {
			v = v*10 + int(c-'0')
		}
		return v
	}

	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	const MAXN = 100005
	min_X := make([]int, MAXN)
	max_X := make([]int, MAXN)
	for i := range min_X {
		min_X[i] = 1e9
		max_X[i] = -1e9
	}

	for {
		scanner.Scan()
		s := scanner.Bytes()
		if len(s) == 0 {
			break
		}
		N := 0
		for _, c := range s {
			N = N*10 + int(c-'0')
		}
		M := readInt()
		if N == 0 && M == 0 {
			break
		}

		min_y := int(1e9)
		max_y := int(-1e9)

		for i := 0; i < M; i++ {
			x := readInt()
			y := readInt()
			if x < min_X[y] {
				min_X[y] = x
			}
			if x > max_X[y] {
				max_X[y] = x
			}
			if y < min_y {
				min_y = y
			}
			if y > max_y {
				max_y = y
			}
		}

		var points []Point
		for y := min_y; y < max_y; y++ {
			if min_X[y] > max_X[y] || min_X[y+1] > max_X[y+1] {
				continue
			}
			left := min_X[y]
			if min_X[y+1] > left {
				left = min_X[y+1]
			}

			right := max_X[y]
			if max_X[y+1] < right {
				right = max_X[y+1]
			}
			right -= 1

			if left <= right {
				points = append(points, Point{left, y})
				if left != right {
					points = append(points, Point{right, y})
				}
			}
		}

		for y := min_y; y <= max_y; y++ {
			min_X[y] = 1e9
			max_X[y] = -1e9
		}

		sort.Slice(points, func(i, j int) bool {
			if points[i].x == points[j].x {
				return points[i].y < points[j].y
			}
			return points[i].x < points[j].x
		})

		crossProduct := func(p1, p2, p3 Point) int64 {
			return int64(p2.x-p1.x)*int64(p3.y-p2.y) - int64(p2.y-p1.y)*int64(p3.x-p2.x)
		}

		var upper []Point
		for _, p := range points {
			for len(upper) >= 2 {
				if crossProduct(upper[len(upper)-2], upper[len(upper)-1], p) >= 0 {
					upper = upper[:len(upper)-1]
				} else {
					break
				}
			}
			upper = append(upper, p)
		}

		var lower []Point
		for i := len(points) - 1; i >= 0; i-- {
			p := points[i]
			for len(lower) >= 2 {
				if crossProduct(lower[len(lower)-2], lower[len(lower)-1], p) >= 0 {
					lower = lower[:len(lower)-1]
				} else {
					break
				}
			}
			lower = append(lower, p)
		}

		var hull []Point
		if len(upper) > 0 {
			hull = append(hull, upper[:len(upper)-1]...)
		}
		if len(lower) > 0 {
			hull = append(hull, lower[:len(lower)-1]...)
		}

		fmt.Fprintf(out, "%d\n", len(hull))
		for _, p := range hull {
			fmt.Fprintf(out, "%d %d\n", p.x, p.y)
		}
	}
}
```