← Home
```go
package main

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

type FastScanner struct {
	r *bufio.Reader
}

func NewFastScanner() *FastScanner {
	return &FastScanner{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
}

func (fs *FastScanner) NextInt() int {
	sign, val := 1, 0
	c, err := fs.r.ReadByte()
	for (c < '0' || c > '9') && c != '-' {
		c, err = fs.r.ReadByte()
		if err != nil {
			return 0
		}
	}
	if c == '-' {
		sign = -1
		c, _ = fs.r.ReadByte()
	}
	for c >= '0' && c <= '9' {
		val = val*10 + int(c-'0')
		c, err = fs.r.ReadByte()
		if err != nil {
			break
		}
	}
	if err == nil && (c < '0' || c > '9') && c != '-' {
		fs.r.UnreadByte()
	}
	return sign * val
}

type DSU struct {
	parent []int
	size   []int
	mx     []int
}

func NewDSU(n int) *DSU {
	parent := make([]int, n)
	size := make([]int, n)
	mx := make([]int, n)
	for i := 0; i < n; i++ {
		parent[i] = i
		size[i] = 1
		mx[i] = i
	}
	return &DSU{parent: parent, size: size, mx: mx}
}

func (d *DSU) Find(x int) int {
	for d.parent[x] != x {
		d.parent[x] = d.parent[d.parent[x]]
		x = d.parent[x]
	}
	return x
}

func (d *DSU) Union(a, b int) int {
	ra := d.Find(a)
	rb := d.Find(b)
	if ra == rb {
		return ra
	}
	if d.size[ra] < d.size[rb] {
		ra, rb = rb, ra
	}
	d.parent[rb] = ra
	d.size[ra] += d.size[rb]
	if d.mx[rb] > d.mx[ra] {
		d.mx[ra] = d.mx[rb]
	}
	return ra
}

func main() {
	fs := NewFastScanner()
	n := fs.NextInt()
	m := fs.NextInt()

	dsu := NewDSU(n)
	for i := 0; i < m; i++ {
		u := fs.NextInt() - 1
		v := fs.NextInt() - 1
		dsu.Union(u, v)
	}

	ans := 0
	for i := 0; i < n; {
		root := dsu.Find(i)
		r := dsu.mx[root]
		for j := i + 1; j <= r; j++ {
			rj := dsu.Find(j)
			if rj != root {
				ans++
				root = dsu.Union(root, rj)
				if dsu.mx[root] > r {
					r = dsu.mx[root]
				}
			}
		}
		i = r + 1
	}

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	fmt.Fprintln(out, ans)
	out.Flush()
}
```