human
I found an interesting problem on https://codeforces.com/problemset/problem/1253/D:
You're given an undirected graph with $n$ nodes and $m$ edges. Nodes are numbered from $1$ to $n$.

The graph is considered harmonious if and only if the following property holds:  For every triple of integers $(l, m, r)$ such that $1 \le l < m < r \le n$, if there exists a path going from node $l$ to node $r$, then there exists a path going from node $l$ to node $m$. 

In other words, in a harmonious graph, if from a node $l$ we can reach a node $r$ through edges ($l < r$), then we should able to reach nodes $(l+1), (l+2), \ldots, (r-1)$ too.

What is the minimum number of edges we need to add to make the graph harmonious? 

-----Input-----

The first line contains two integers $n$ and $m$ ($3 \le n \le 200\ 000$ and $1 \le m \le 200\ 000$).

The $i$-th of the next $m$ lines contains two integers $u_i$ and $v_i$ ($1 \le u_i, v_i \le n$, $u_i \neq v_i$), that mean that there's an edge between nodes $u$ and $v$.

It is guaranteed that the given graph is simple (there is no self-loop, and there is at most one edge between every pair of nodes).

-----Output-----

Print the minimum number of edges we have to add to the graph to make it harmonious.

-----Examples-----
Input
14 8
1 2
2 7
3 4
6 3
5 7
3 8
6 8
11 12

Output
1

Input
200000 3
7 9
9 8
4 5

Output
0


-----Note-----

In the first example, the given graph is not harmonious (for instance, $1 < 6 < 7$, node $1$ can reach node $7$ through the path $1 \rightarrow 2 \rightarrow 7$, but node $1$ can't reach node $6$). However adding the edge $(2, 4)$ is sufficient to make it harmonious.

In the second example, the given graph is already harmonious.

I tried it in Python, but could not do it. Can you solve it?

 Give me a Python program to print the minimum number of edges we have to add to the graph to make it harmonious?
assistant
#Here is Python program to print the minimum number of edges we have to add to the graph to make it harmonious.

# unionfind
class Uf:
    def __init__(self, N):
        self.p = list(range(N))
        self.rank = [0] * N
        self.size = [1] * N

    def root(self, x):
        if self.p[x] != x:
            self.p[x] = self.root(self.p[x])

        return self.p[x]

    def same(self, x, y):
        return self.root(x) == self.root(y)

    def unite(self, x, y):
        u = self.root(x)
        v = self.root(y)

        if u == v: return

        if self.rank[u] < self.rank[v]:
            self.p[u] = v
            self.size[v] += self.size[u]
            self.size[u] = 0
        else:
            self.p[v] = u
            self.size[u] += self.size[v]
            self.size[v] = 0

            if self.rank[u] == self.rank[v]:
                self.rank[u] += 1

    def count(self, x):
        return self.size[self.root(x)]

import sys
from operator import itemgetter
def main():
    input = sys.stdin.readline
    N, M = list(map(int, input().split()))
    # harmonious <=> l < m < r で、l から r に辿り着けるなら、l から m に辿り着ける

    uf = Uf(N+1)
    for u, v in zip(*[iter(map(int, sys.stdin.read().split()))]*2):
        uf.unite(u, v)

    L = [10**9] * (N+1)
    R = [-1] * (N+1)
    for i in range(1, N+1):
        r = uf.root(i)
        L[r] = min(L[r], i)
        R[r] = max(R[r], i)
    ans = 0
    LR = []
    for l, r in zip(L, R):
        if r != -1:
            LR.append((l, r))
    LR.sort(key=itemgetter(0))
    rr = -1
    for l, r in LR:
        if rr > l:
            ans += 1
        rr = max(rr, r)
    print(ans)

main()