import java.io.*;
import java.util.*;

public class Solution {
    public static void main(String[] args) {
        FastReader in = new FastReader();
        int n = in.nextInt();
        int m = in.nextInt();
        DisjointUnionSets set = new DisjointUnionSets(n);
        for (int i = 0; i < m; i++) {
            set.union(in.nextInt(), in.nextInt());
        }
        HashMap<Integer, int[]> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            if(set.rank[set.find(i)] == 0)continue;
            int[] len = map.computeIfAbsent(set.find(i), k -> new int[]{k, k});
            len[0] = Math.min(len[0], i);
            len[1] = Math.max(len[1], i);
        }
        int cnt = 0;
        for(int[] interval : map.values()){
            for(int i = interval[0] + 1; i < interval[1]; i++){
                if(set.rank[set.find(i)] == 0)continue;
                if(set.find(i) != set.find(interval[0])){
                    set.union(i, interval[0]);
                    cnt++;
                }
            }
        }
        System.out.println(cnt);
    }

    static class DisjointUnionSets {
        int[] rank, parent;
        int n;

        public DisjointUnionSets(int n) {
            rank = new int[n];
            parent = new int[n];
            this.n = n;
            makeSet();
        }

        void makeSet() {
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]);
            }

            return parent[x];
        }

        void union(int x, int y) {
            int xRoot = find(x), yRoot = find(y);
            if (xRoot == yRoot)
                return;
            if (rank[xRoot] < rank[yRoot])
                parent[xRoot] = yRoot;

            else if (rank[yRoot] < rank[xRoot])
                parent[yRoot] = xRoot;

            else {
                parent[yRoot] = xRoot;
                rank[xRoot] = rank[xRoot] + 1;
            }
        }
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new
                    InputStreamReader(System.in));
        }

        public int[] nextIntArray(int n) {
            int[] array = new int[n];
            for (int i = 0; i < n; ++i) array[i] = nextInt();
            return array;
        }

        public int[] nextSortedIntArray(int n) {
            int array[] = nextIntArray(n);
            Arrays.sort(array);
            return array;
        }

        public int[] nextSumIntArray(int n) {
            int[] array = new int[n];
            array[0] = nextInt();
            for (int i = 1; i < n; ++i) array[i] = array[i - 1] + nextInt();
            return array;
        }

        public long[] nextLongArray(int n) {
            long[] array = new long[n];
            for (int i = 0; i < n; ++i) array[i] = nextLong();
            return array;
        }

        public long[] nextSumLongArray(int n) {
            long[] array = new long[n];
            array[0] = nextInt();
            for (int i = 1; i < n; ++i) array[i] = array[i - 1] + nextInt();
            return array;
        }

        public long[] nextSortedLongArray(int n) {
            long array[] = nextLongArray(n);
            Arrays.sort(array);
            return array;
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.io.*;
import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.Collectors;

public class Solution {
    public static void main(String[] args) {
        FastReader in = new FastReader();
        int n = in.nextInt();
        int m = in.nextInt();
        DisjointUnionSets set = new DisjointUnionSets(n);
        for (int i = 0; i < m; i++) {
            set.union(in.nextInt() - 1, in.nextInt() - 1);
        }
        HashMap<Integer, int[]> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            if(set.rank[set.find(i)] == 0)continue;
            int[] len = map.computeIfAbsent(set.find(i), k -> new int[]{k, k});
            len[0] = Math.min(len[0], i);
            len[1] = Math.max(len[1], i);
        }
        int cnt = 0;
        ArrayList<int[]> intervals = new ArrayList<>(map.values());
        HashSet<int[]> blocked = new HashSet<>();
        Collections.sort(intervals, (a, b)->a[0] - b[0]);
        for(int[] interval : intervals){
            if(blocked.contains(interval))continue;
            int max = interval[1];
            for(int i = interval[0] + 1; i <= max; i++){
                if(set.find(i) != set.find(interval[0])){
                    blocked.add(map.computeIfAbsent(set.find(i), k -> new int[]{k, k}));
                    max = Math.max(max, map.computeIfAbsent(set.find(i), k -> new int[]{k, k})[1]);
                    set.union(i, interval[0]);
                    cnt++;
                }
            }
        }
        System.out.println(cnt);
    }

    static class DisjointUnionSets {
        int[] rank, parent;
        int n;

        public DisjointUnionSets(int n) {
            rank = new int[n];
            parent = new int[n];
            this.n = n;
            makeSet();
        }

        void makeSet() {
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]);
            }

            return parent[x];
        }

        void union(int x, int y) {
            int xRoot = find(x), yRoot = find(y);
            if (xRoot == yRoot)
                return;
            if (rank[xRoot] < rank[yRoot])
                parent[xRoot] = yRoot;

            else if (rank[yRoot] < rank[xRoot])
                parent[yRoot] = xRoot;

            else {
                parent[yRoot] = xRoot;
                rank[xRoot] = rank[xRoot] + 1;
            }
        }
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new
                    InputStreamReader(System.in));
        }

        public int[] nextIntArray(int n) {
            int[] array = new int[n];
            for (int i = 0; i < n; ++i) array[i] = nextInt();
            return array;
        }

        public int[] nextSortedIntArray(int n) {
            int array[] = nextIntArray(n);
            Arrays.sort(array);
            return array;
        }

        public int[] nextSumIntArray(int n) {
            int[] array = new int[n];
            array[0] = nextInt();
            for (int i = 1; i < n; ++i) array[i] = array[i - 1] + nextInt();
            return array;
        }

        public long[] nextLongArray(int n) {
            long[] array = new long[n];
            for (int i = 0; i < n; ++i) array[i] = nextLong();
            return array;
        }

        public long[] nextSumLongArray(int n) {
            long[] array = new long[n];
            array[0] = nextInt();
            for (int i = 1; i < n; ++i) array[i] = array[i - 1] + nextInt();
            return array;
        }

        public long[] nextSortedLongArray(int n) {
            long array[] = nextLongArray(n);
            Arrays.sort(array);
            return array;
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.io.*;
import java.util.*;

public class Solution {
    public static void main(String[] args) {
        FastReader in = new FastReader();
        int n = in.nextInt();
        int m = in.nextInt();
        DisjointUnionSets set = new DisjointUnionSets(n);
        for (int i = 0; i < m; i++) {
            set.union(in.nextInt() - 1, in.nextInt() - 1);
        }
        HashMap<Integer, int[]> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            if(set.rank[set.find(i)] == 0)continue;
            int[] len = map.computeIfAbsent(set.find(i), k -> new int[]{k, k});
            len[0] = Math.min(len[0], i);
            len[1] = Math.max(len[1], i);
        }
        int cnt = 0;
        for(int[] interval : map.values()){
            for(int i = interval[0] + 1; i < interval[1]; i++){
//                if(set.rank[set.find(i)] == 0)continue;
                if(set.find(i) != set.find(interval[0])){
                    set.union(i, interval[0]);
                    cnt++;
                }
            }
        }
        System.out.println(cnt);
    }

    static class DisjointUnionSets {
        int[] rank, parent;
        int n;

        public DisjointUnionSets(int n) {
            rank = new int[n];
            parent = new int[n];
            this.n = n;
            makeSet();
        }

        void makeSet() {
            for (int i = 0; i < n; i++) {
                parent[i] = i;
            }
        }

        int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]);
            }

            return parent[x];
        }

        void union(int x, int y) {
            int xRoot = find(x), yRoot = find(y);
            if (xRoot == yRoot)
                return;
            if (rank[xRoot] < rank[yRoot])
                parent[xRoot] = yRoot;

            else if (rank[yRoot] < rank[xRoot])
                parent[yRoot] = xRoot;

            else {
                parent[yRoot] = xRoot;
                rank[xRoot] = rank[xRoot] + 1;
            }
        }
    }

    static class FastReader {
        BufferedReader br;
        StringTokenizer st;

        public FastReader() {
            br = new BufferedReader(new
                    InputStreamReader(System.in));
        }

        public int[] nextIntArray(int n) {
            int[] array = new int[n];
            for (int i = 0; i < n; ++i) array[i] = nextInt();
            return array;
        }

        public int[] nextSortedIntArray(int n) {
            int array[] = nextIntArray(n);
            Arrays.sort(array);
            return array;
        }

        public int[] nextSumIntArray(int n) {
            int[] array = new int[n];
            array[0] = nextInt();
            for (int i = 1; i < n; ++i) array[i] = array[i - 1] + nextInt();
            return array;
        }

        public long[] nextLongArray(int n) {
            long[] array = new long[n];
            for (int i = 0; i < n; ++i) array[i] = nextLong();
            return array;
        }

        public long[] nextSumLongArray(int n) {
            long[] array = new long[n];
            array[0] = nextInt();
            for (int i = 1; i < n; ++i) array[i] = array[i - 1] + nextInt();
            return array;
        }

        public long[] nextSortedLongArray(int n) {
            long array[] = nextLongArray(n);
            Arrays.sort(array);
            return array;
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
}


import java.util.*;
import java.io.*;

public class Solution {
	public static void main (String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String[] temp=br.readLine().trim().split(" ");
		int V=Integer.parseInt(temp[0]);
		int E=Integer.parseInt(temp[1]);
		ArrayList<ArrayList<Integer>> graph=new ArrayList<>();
		for(int i=0;i<=V;i++)
		{
		    graph.add(new ArrayList<>());
		}
		for(int i=0;i<E;i++)
		{
		    temp=br.readLine().trim().split(" ");
		    int u=Integer.parseInt(temp[0]);
		    int v=Integer.parseInt(temp[1]);
		    graph.get(u).add(v);
		    graph.get(v).add(u);
		}
		System.out.println(minEdges(graph));
	}
	public static int minEdges(ArrayList<ArrayList<Integer>> graph)
	{
	    ArrayList<Interval> intervals=new ArrayList<>();
	    int V=graph.size()-1;
	    boolean[] visited=new boolean[V+1];
	    for(int i=1;i<=V;i++)
	    {
	        if(visited[i]==false)
	        {
	            Interval interval=dfs(graph,i,visited);
	            intervals.add(interval);
	        }
	    }
	    Collections.sort(intervals);
	    int ans=0;
	    for(int i=0;i<intervals.size();)
	    {
	        int max=intervals.get(i).max;
	        int j=i+1;
	        while(j<intervals.size() && intervals.get(j).min<max)
	        {
	            max=Math.max(max,intervals.get(j).max);
	            ans++;
	            j++;
	        }
	        i=j;
	    }
	    return ans;
	}
	public static Interval dfs(ArrayList<ArrayList<Integer>> graph,int start,boolean[] visited)
	{
	    visited[start]=true;
	    int min=start,max=start;
	    for(int i=0;i<graph.get(start).size();i++)
	    {
	        if(visited[graph.get(start).get(i)]==false)
	        {
	            Interval smallAns=dfs(graph,graph.get(start).get(i),visited);
	            min=Math.min(min,smallAns.min);
	            max=Math.max(max,smallAns.max);
	        }
	    }
	    Interval ans=new Interval();
	    ans.min=min;
	    ans.max=max;
	    return ans;
	}
}
class Interval implements Comparable<Interval>{
    int min;
    int max;

    public int compareTo(Interval i)
    {
        return this.min-i.min;
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.DataInputStream;
import java.util.Vector;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Comparator;
import java.util.Collections;
import java.util.TreeSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author xwchen
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            final int N = 200002;
            DisjointSet ds = new DisjointSet(200002);
            int[] mn = new int[N];
            int[] mx = new int[N];
            for (int i = 1; i <= n; ++i) {
                mn[i] = mx[i] = i;
            }

            for (int i = 0; i < m; ++i) {
                int a = in.nextInt();
                int b = in.nextInt();

                int da = ds.find(a);
                int db = ds.find(b);
                if (da != db) {
                    ds.union(da, db);
                    mn[da] = Math.min(mn[da], a);
                    mn[da] = Math.min(mn[da], b);
                    mn[da] = Math.min(mn[da], mn[db]);

                    mx[da] = Math.max(mx[da], a);
                    mx[da] = Math.max(mx[da], b);
                    mx[da] = Math.max(mx[da], mx[db]);
                }
            }
            Vector<Segment> segments = new Vector<>();
            TreeSet<Integer> set = new TreeSet<>();
            for (int i = 1; i <= n; ++i) {
                int da = ds.find(i);
                if (!set.contains(da)) {
                    set.add(da);
                    segments.add(new Segment(mn[da], mx[da]));
                }
            }
            Collections.sort(segments, new Comparator<Segment>() {

                public int compare(Segment o1, Segment o2) {
                    if (o1.a != o2.a) return o1.a - o2.a;
                    else return o1.b - o2.b;
                }
            });
            int result = 0;
            Segment last = null;
            for (Segment seg : segments) {
                //out.println(seg.a+" "+seg.b);
                if (last == null) {
                    last = seg;
                } else {
                    if (seg.a < last.b) {
                        result++;
                        if (seg.b > last.b) {
                            last = seg;
                        } else {

                        }
                    } else {
                        last = seg;
                    }
                }
            }
            out.println(result);
        }

        public class Segment {
            int a;
            int b;

            public Segment(int a, int b) {
                this.a = a;
                this.b = b;
            }

        }

    }

    static class DisjointSet {
        int[] f;

        public DisjointSet(int n) {
            f = new int[n + 1];
            for (int i = 1; i <= n; ++i) {
                f[i] = i;
            }
        }

        public int find(int x) {
            return f[x] == x ? x : (f[x] = find(f[x]));
        }

        public void union(int x, int y) {
            f[find(y)] = find(x);
        }

    }

    static class InputReader {
        final private int BUFFER_SIZE = 1 << 10;
        private DataInputStream in;
        private byte[] buffer;
        private int bufferPointer;
        private int bytesRead;

        public InputReader(InputStream inputStream) {
            this.in = new DataInputStream(inputStream);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public int nextInt() {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() {
            try {
                bytesRead = in.read(buffer, bufferPointer = 0, BUFFER_SIZE);
                if (bytesRead == -1)
                    buffer[0] = -1;
            } catch (IOException e) {
                throw new InputMismatchException();
            }
        }

        private byte read() {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.DataInputStream;
import java.util.Vector;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Comparator;
import java.util.Collections;
import java.util.TreeSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author xwchen
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            final int N = 200002;
            DisjointSet ds = new DisjointSet(200002);
            int[] mn = new int[N];
            int[] mx = new int[N];
            for (int i = 1; i <= n; ++i) {
                mn[i] = mx[i] = i;
            }

            for (int i = 0; i < m; ++i) {
                int a = in.nextInt();
                int b = in.nextInt();
                ds.union(a, b);
                int da = ds.find(a);
                mn[da] = Math.min(mn[da], a);
                mn[da] = Math.min(mn[da], b);

                mx[da] = Math.max(mx[da], a);
                mx[da] = Math.max(mx[da], b);
            }
            Vector<Segment> segments = new Vector<>();
            TreeSet<Integer> set = new TreeSet<>();
            for (int i = 1; i <= n; ++i) {
                int da = ds.find(i);
                if (!set.contains(da) && mn[da] < mx[da]) {
                    set.add(da);
                    segments.add(new Segment(mn[da], mx[da]));
                }
            }
            Collections.sort(segments, new Comparator<Segment>() {

                public int compare(Segment o1, Segment o2) {
                    if (o1.a != o2.a) return o1.a - o2.a;
                    else return o1.b - o2.b;
                }
            });
            int result = 0;
            Segment last = null;
            for (Segment seg : segments) {
                //out.println(seg.a+" "+seg.b);
                if (last == null) {
                    last = seg;
                } else {
                    if (seg.a < last.b) {
                        result++;
                        if (seg.b > last.b) {
                            last = seg;
                        } else {

                        }
                    } else {
                        last = seg;
                    }
                }
            }
            out.println(result);
        }

        public class Segment {
            int a;
            int b;

            public Segment(int a, int b) {
                this.a = a;
                this.b = b;
            }

        }

    }

    static class DisjointSet {
        int[] f;

        public DisjointSet(int n) {
            f = new int[n + 1];
            for (int i = 1; i <= n; ++i) {
                f[i] = i;
            }
        }

        public int find(int x) {
            return f[x] == x ? x : (f[x] = find(f[x]));
        }

        public void union(int x, int y) {
            f[find(y)] = find(x);
        }

    }

    static class InputReader {
        final private int BUFFER_SIZE = 1 << 10;
        private DataInputStream in;
        private byte[] buffer;
        private int bufferPointer;
        private int bytesRead;

        public InputReader(InputStream inputStream) {
            this.in = new DataInputStream(inputStream);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public int nextInt() {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() {
            try {
                bytesRead = in.read(buffer, bufferPointer = 0, BUFFER_SIZE);
                if (bytesRead == -1)
                    buffer[0] = -1;
            } catch (IOException e) {
                throw new InputMismatchException();
            }
        }

        private byte read() {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.DataInputStream;
import java.util.Vector;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Comparator;
import java.util.Collections;
import java.util.TreeSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author xwchen
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            final int N = 200002;
            DisjointSet ds = new DisjointSet(200002);
            int[] mn = new int[N];
            int[] mx = new int[N];
            for (int i = 1; i <= n; ++i) {
                mn[i] = mx[i] = i;
            }

            for (int i = 0; i < m; ++i) {
                int a = in.nextInt();
                int b = in.nextInt();
                ds.union(a, b);
                int da = ds.find(a);
                mn[da] = Math.min(mn[da], a);
                mn[da] = Math.min(mn[da], b);

                mx[da] = Math.max(mx[da], a);
                mx[da] = Math.max(mx[da], b);
            }
            Vector<Segment> segments = new Vector<>();
            TreeSet<Integer> set = new TreeSet<>();
            for (int i = 1; i <= n; ++i) {
                int da = ds.find(i);
                if (!set.contains(da)) {
                    set.add(da);
                    segments.add(new Segment(mn[da], mx[da]));
                }
            }
            Collections.sort(segments, new Comparator<Segment>() {

                public int compare(Segment o1, Segment o2) {
                    if (o1.a != o2.a) return o1.a - o2.a;
                    else return o1.b - o2.b;
                }
            });
            int result = 0;
            Segment last = null;
            for (Segment seg : segments) {
                //out.println(seg.a+" "+seg.b);
                if (last == null) {
                    last = seg;
                } else {
                    if (seg.a < last.b) {
                        result++;
                        if (seg.b > last.b) {
                            last = seg;
                        } else {

                        }
                    } else {
                        last = seg;
                    }
                }
            }
            out.println(result);
        }

        public class Segment {
            int a;
            int b;

            public Segment(int a, int b) {
                this.a = a;
                this.b = b;
            }

        }

    }

    static class DisjointSet {
        int[] f;

        public DisjointSet(int n) {
            f = new int[n + 1];
            for (int i = 1; i <= n; ++i) {
                f[i] = i;
            }
        }

        public int find(int x) {
            return f[x] == x ? x : (f[x] = find(f[x]));
        }

        public void union(int x, int y) {
            f[find(y)] = find(x);
        }

    }

    static class InputReader {
        final private int BUFFER_SIZE = 1 << 10;
        private DataInputStream in;
        private byte[] buffer;
        private int bufferPointer;
        private int bytesRead;

        public InputReader(InputStream inputStream) {
            this.in = new DataInputStream(inputStream);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public int nextInt() {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() {
            try {
                bytesRead = in.read(buffer, bufferPointer = 0, BUFFER_SIZE);
                if (bytesRead == -1)
                    buffer[0] = -1;
            } catch (IOException e) {
                throw new InputMismatchException();
            }
        }

        private byte read() {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.DataInputStream;
import java.util.Vector;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Comparator;
import java.util.Collections;
import java.util.TreeSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author xwchen
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            final int N = 200002;
            DisjointSet ds = new DisjointSet(200002);
            int[] mn = new int[N];
            int[] mx = new int[N];
            for (int i = 1; i <= n; ++i) {
                mn[i] = mx[i] = i;
            }

            for (int i = 0; i < m; ++i) {
                int a = in.nextInt();
                int b = in.nextInt();
                ds.union(a, b);
                int da = ds.find(a);
                mn[da] = Math.min(mn[da], a);
                mn[da] = Math.min(mn[da], b);

                mx[da] = Math.max(mx[da], a);
                mx[da] = Math.max(mx[da], b);
            }
            Vector<Segment> segments = new Vector<>();
            TreeSet<Integer> set = new TreeSet<>();
            for (int i = 1; i <= n; ++i) {
                int da = ds.find(i);
                if (!set.contains(da) && mn[da] < mx[da] - 1) {
                    set.add(da);
                    segments.add(new Segment(mn[da], mx[da]));
                }
            }
            Collections.sort(segments, new Comparator<Segment>() {

                public int compare(Segment o1, Segment o2) {
                    if (o1.a != o2.a) return o1.a - o2.a;
                    else return o1.b - o2.b;
                }
            });
            int result = 0;
            Segment last = null;
            for (Segment seg : segments) {
                //out.println(seg.a+" "+seg.b);
                if (last == null) {
                    last = seg;
                } else {
                    if (seg.a < last.b) {
                        result++;
                        if (seg.b > last.b) {
                            last = seg;
                        } else {

                        }
                    } else {
                        last = seg;
                    }
                }
            }
            out.println(result);
        }

        public class Segment {
            int a;
            int b;

            public Segment(int a, int b) {
                this.a = a;
                this.b = b;
            }

        }

    }

    static class DisjointSet {
        int[] f;

        public DisjointSet(int n) {
            f = new int[n + 1];
            for (int i = 1; i <= n; ++i) {
                f[i] = i;
            }
        }

        public int find(int x) {
            return f[x] == x ? x : (f[x] = find(f[x]));
        }

        public void union(int x, int y) {
            f[find(y)] = find(x);
        }

    }

    static class InputReader {
        final private int BUFFER_SIZE = 1 << 10;
        private DataInputStream in;
        private byte[] buffer;
        private int bufferPointer;
        private int bytesRead;

        public InputReader(InputStream inputStream) {
            this.in = new DataInputStream(inputStream);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public int nextInt() {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() {
            try {
                bytesRead = in.read(buffer, bufferPointer = 0, BUFFER_SIZE);
                if (bytesRead == -1)
                    buffer[0] = -1;
            } catch (IOException e) {
                throw new InputMismatchException();
            }
        }

        private byte read() {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.DataInputStream;
import java.util.Vector;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Comparator;
import java.util.Collections;
import java.util.TreeSet;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author xwchen
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();
            final int N = 200002;
            DisjointSet ds = new DisjointSet(200002);
            int[] mn = new int[N];
            int[] mx = new int[N];
            for (int i = 1; i <= n; ++i) {
                mn[i] = mx[i] = i;
            }

            for (int i = 0; i < m; ++i) {
                int a = in.nextInt();
                int b = in.nextInt();

                int da = ds.find(a);
                int db = ds.find(b);
                if (da != db) {
                    ds.union(da, db);
                    mn[da] = Math.min(mn[da], a);
                    mn[da] = Math.min(mn[da], b);

                    mx[da] = Math.max(mx[da], a);
                    mx[da] = Math.max(mx[da], b);
                }
            }
            Vector<Segment> segments = new Vector<>();
            TreeSet<Integer> set = new TreeSet<>();
            for (int i = 1; i <= n; ++i) {
                int da = ds.find(i);
                if (!set.contains(da)) {
                    set.add(da);
                    segments.add(new Segment(mn[da], mx[da]));
                }
            }
            Collections.sort(segments, new Comparator<Segment>() {

                public int compare(Segment o1, Segment o2) {
                    if (o1.a != o2.a) return o1.a - o2.a;
                    else return o1.b - o2.b;
                }
            });
            int result = 0;
            Segment last = null;
            for (Segment seg : segments) {
                //out.println(seg.a+" "+seg.b);
                if (last == null) {
                    last = seg;
                } else {
                    if (seg.a < last.b) {
                        result++;
                        if (seg.b > last.b) {
                            last = seg;
                        } else {

                        }
                    } else {
                        last = seg;
                    }
                }
            }
            out.println(result);
        }

        public class Segment {
            int a;
            int b;

            public Segment(int a, int b) {
                this.a = a;
                this.b = b;
            }

        }

    }

    static class DisjointSet {
        int[] f;

        public DisjointSet(int n) {
            f = new int[n + 1];
            for (int i = 1; i <= n; ++i) {
                f[i] = i;
            }
        }

        public int find(int x) {
            return f[x] == x ? x : (f[x] = find(f[x]));
        }

        public void union(int x, int y) {
            f[find(y)] = find(x);
        }

    }

    static class InputReader {
        final private int BUFFER_SIZE = 1 << 10;
        private DataInputStream in;
        private byte[] buffer;
        private int bufferPointer;
        private int bytesRead;

        public InputReader(InputStream inputStream) {
            this.in = new DataInputStream(inputStream);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public int nextInt() {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() {
            try {
                bytesRead = in.read(buffer, bufferPointer = 0, BUFFER_SIZE);
                if (bytesRead == -1)
                    buffer[0] = -1;
            } catch (IOException e) {
                throw new InputMismatchException();
            }
        }

        private byte read() {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

    }
}


/* بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ */
//codeforces1253D
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Math.*;
import java.math.*;

public class Main{

	static PrintWriter go = new PrintWriter(System.out);

	public static void main(String args[]) throws IOException,FileNotFoundException {
		BufferedReader gi = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		int[] li = parseArray(gi);
		int n = li[0], m = li[1];
		UnionFind ufds = new UnionFind(n + 1);
		for ( int k = 0; k < m; k++ ){
			li = parseArray(gi);
			ufds.unify(li[0], li[1]);
		}
		ArrayList<Integer>[] components = new ArrayList[n + 1];
		for ( int k = 0; k <= n; k++ ) components[k] = new ArrayList<>();
		for ( int k = 1; k <= n; k++ )
			components[ufds.find(k)].add(k);
		for ( int k = 1; k <= n; k++ ) Collections.sort(components[k]);
		int ans = 0;
		int l = 1, r = 1;
		while (true) {
			l = r + 1;
			if (l > n) break;
			if (components[l].isEmpty()) { r++; continue; }
			r = components[l].get(components[l].size() - 1);
			for ( int k = l + 1; k <= r; k++ ){
				if (!ufds.connected(l, k)) {
					ufds.unify(l, k);
					ans++;
				}
			}
		}
		/*
		for (ArrayList<Integer> component : components) {
			if (component.isEmpty()) continue;
			int root = component.get(0);
			for ( int k = root + 1; k < component.get(component.size() - 1); k++ ){
				if (!ufds.connected(root, k)) {
					ufds.unify(root, k);
					ans++;
				}
			}
		}
		*/
		go.println(ans);
		go.close();
	}

	static int[] parseArray(BufferedReader gi) throws IOException{
		String[] line = gi.readLine().split(" ");
		int[] rez = new int[line.length];
		for ( int k = 0; k < line.length; k++){
			rez[k] =  Integer.parseInt(line[k]);
		}
		return rez;
	}

}

class UnionFind {
	private int size;
	private int[] sz;
	private int[] id;
	private int numComponents;

	public UnionFind(int size) {
		this.size = numComponents = size;
		sz = new int[size];
		id = new int[size];
		for(int i = 0; i < size; i++) {
			id[i] = i;
			sz[i] = 1;
		}

	}

	public int find(int p) {
		int root = p;
		while( root != id[root] )
			root = id[root];
		while(p != root) {
			int next = id[p];
			id[p] = root;
			p = next;
		}
		return root;
	}

	public boolean connected(int p, int q) {
		return find(p) == find(q);
	}

	public int componentSize(int p) {
		return sz[find(p)];
	}

	public int size() {
		return size;
	}

	public int components() {
		return numComponents;
	}

	public void unify(int p, int q) {
		int root1 = find(p);
		int root2 = find(q);
		if (root1 == root2) return;
		if (sz[root1] < sz[root2]) {
			sz[root2] += sz[root1];
			id[root1] = root2;
		} else {
			sz[root1] += sz[root2];
			id[root2] = root1;
		}
		numComponents--;
	}

}


/* بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ */
//codeforces1253D
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Math.*;
import java.math.*;

public class Main{

	static PrintWriter go = new PrintWriter(System.out);

	public static void main(String args[]) throws IOException,FileNotFoundException {
		BufferedReader gi = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		int[] l = parseArray(gi);
		int n = l[0], m = l[1];
		UnionFind ufds = new UnionFind(n + 1);
		for ( int k = 0; k < m; k++ ){
			l = parseArray(gi);
			ufds.unify(l[0], l[1]);
		}
		ArrayList<Integer>[] components = new ArrayList[n + 1];
		for ( int k = 0; k <= n; k++ ) components[k] = new ArrayList<>();
		for ( int k = 1; k <= n; k++ )
			components[ufds.find(k)].add(k);
		for ( int k = 1; k <= n; k++ ) Collections.sort(components[k]);
		int ans = 0;
		for (ArrayList<Integer> component : components) {
			if (component.isEmpty()) continue;
			int root = component.get(0);
			for ( int k = root + 1; k < component.get(component.size() - 1); k++ ){
				if (!ufds.connected(root, k)) {
					ufds.unify(root, k);
					ans++;
				}
			}
		}
		go.println(ans);
		go.close();
	}

	static int[] parseArray(BufferedReader gi) throws IOException{
		String[] line = gi.readLine().split(" ");
		int[] rez = new int[line.length];
		for ( int k = 0; k < line.length; k++){
			rez[k] =  Integer.parseInt(line[k]);
		}
		return rez;
	}

}

class UnionFind {
	private int size;
	private int[] sz;
	private int[] id;
	private int numComponents;

	public UnionFind(int size) {
		this.size = numComponents = size;
		sz = new int[size];
		id = new int[size];
		for(int i = 0; i < size; i++) {
			id[i] = i;
			sz[i] = 1;
		}

	}

	public int find(int p) {
		int root = p;
		while( root != id[root] )
			root = id[root];
		while(p != root) {
			int next = id[p];
			id[p] = root;
			p = next;
		}
		return root;
	}

	public boolean connected(int p, int q) {
		return find(p) == find(q);
	}

	public int componentSize(int p) {
		return sz[find(p)];
	}

	public int size() {
		return size;
	}

	public int components() {
		return numComponents;
	}

	public void unify(int p, int q) {
		int root1 = find(p);
		int root2 = find(q);
		if (root1 == root2) return;
		if (sz[root1] < sz[root2]) {
			sz[root2] += sz[root1];
			id[root1] = root2;
		} else {
			sz[root1] += sz[root2];
			id[root2] = root1;
		}
		numComponents--;
	}

}


/* بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ */
//codeforces1253D
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Math.*;
import java.math.*;

public class Main{

	static PrintWriter go = new PrintWriter(System.out);

	public static void main(String args[]) throws IOException,FileNotFoundException {
		BufferedReader gi = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		int[] li = parseArray(gi);
		int n = li[0], m = li[1];
		UnionFind ufds = new UnionFind(n + 1);
		for ( int k = 0; k < m; k++ ){
			li = parseArray(gi);
			ufds.unify(li[0], li[1]);
		}
		ArrayList<Integer>[] components = new ArrayList[n + 1];
		for ( int k = 0; k <= n; k++ ) components[k] = new ArrayList<>();
		for ( int k = 1; k <= n; k++ )
			components[ufds.find(k)].add(k);
		for ( int k = 1; k <= n; k++ ) Collections.sort(components[k]);
		int ans = 0;
		int l = 1, r = 0;
		while (true) {
			l = r + 1;
			if (l > n) break;
			r = components[ufds.find(l)].get(components[ufds.find(l)].size() - 1);
			for ( int k = l + 1; k <= r; k++ ){
				r = max(r, components[ufds.find(k)].get(components[ufds.find(k)].size() - 1));
				if (!ufds.connected(l, k)) {
					ufds.unify(l, k);
					ans++;
				}
			}
		}
		go.println(ans);
		go.close();
	}

	static int[] parseArray(BufferedReader gi) throws IOException{
		String[] line = gi.readLine().split(" ");
		int[] rez = new int[line.length];
		for ( int k = 0; k < line.length; k++){
			rez[k] =  Integer.parseInt(line[k]);
		}
		return rez;
	}

}

class UnionFind {
	private int size;
	private int[] sz;
	private int[] id;
	private int numComponents;

	public UnionFind(int size) {
		this.size = numComponents = size;
		sz = new int[size];
		id = new int[size];
		for(int i = 0; i < size; i++) {
			id[i] = i;
			sz[i] = 1;
		}

	}

	public int find(int p) {
		int root = p;
		while( root != id[root] )
			root = id[root];
		while(p != root) {
			int next = id[p];
			id[p] = root;
			p = next;
		}
		return root;
	}

	public boolean connected(int p, int q) {
		return find(p) == find(q);
	}

	public int componentSize(int p) {
		return sz[find(p)];
	}

	public int size() {
		return size;
	}

	public int components() {
		return numComponents;
	}

	public void unify(int p, int q) {
		int root1 = find(p);
		int root2 = find(q);
		if (root1 == root2) return;
		if (sz[root1] < sz[root2]) {
			sz[root2] += sz[root1];
			id[root1] = root2;
		} else {
			sz[root1] += sz[root2];
			id[root2] = root1;
		}
		numComponents--;
	}

}


/* بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ */
//codeforces1253D
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.Math.*;
import java.math.*;

public class Main{

	static PrintWriter go = new PrintWriter(System.out);

	public static void main(String args[]) throws IOException,FileNotFoundException {
		BufferedReader gi = new BufferedReader(new InputStreamReader(System.in, "ISO-8859-1"));
		int[] li = parseArray(gi);
		int n = li[0], m = li[1];
		UnionFind ufds = new UnionFind(n + 1);
		for ( int k = 0; k < m; k++ ){
			li = parseArray(gi);
			ufds.unify(li[0], li[1]);
		}
		ArrayList<Integer>[] components = new ArrayList[n + 1];
		for ( int k = 0; k <= n; k++ ) components[k] = new ArrayList<>();
		for ( int k = 1; k <= n; k++ )
			components[ufds.find(k)].add(k);
		for ( int k = 1; k <= n; k++ ) Collections.sort(components[k]);
		int ans = 0;
		int l = 1, r = 0;
		while (true) {
			l = r + 1;
			if (l > n) break;
			if (components[l].isEmpty()) { r++; continue; }
			r = components[l].get(components[l].size() - 1);
			for ( int k = l + 1; k <= r; k++ ){
				if (!ufds.connected(l, k)) {
					ufds.unify(l, k);
					ans++;
				}
			}
		}
		/*
		for (ArrayList<Integer> component : components) {
			if (component.isEmpty()) continue;
			int root = component.get(0);
			for ( int k = root + 1; k < component.get(component.size() - 1); k++ ){
				if (!ufds.connected(root, k)) {
					ufds.unify(root, k);
					ans++;
				}
			}
		}
		*/
		go.println(ans);
		go.close();
	}

	static int[] parseArray(BufferedReader gi) throws IOException{
		String[] line = gi.readLine().split(" ");
		int[] rez = new int[line.length];
		for ( int k = 0; k < line.length; k++){
			rez[k] =  Integer.parseInt(line[k]);
		}
		return rez;
	}

}

class UnionFind {
	private int size;
	private int[] sz;
	private int[] id;
	private int numComponents;

	public UnionFind(int size) {
		this.size = numComponents = size;
		sz = new int[size];
		id = new int[size];
		for(int i = 0; i < size; i++) {
			id[i] = i;
			sz[i] = 1;
		}

	}

	public int find(int p) {
		int root = p;
		while( root != id[root] )
			root = id[root];
		while(p != root) {
			int next = id[p];
			id[p] = root;
			p = next;
		}
		return root;
	}

	public boolean connected(int p, int q) {
		return find(p) == find(q);
	}

	public int componentSize(int p) {
		return sz[find(p)];
	}

	public int size() {
		return size;
	}

	public int components() {
		return numComponents;
	}

	public void unify(int p, int q) {
		int root1 = find(p);
		int root2 = find(q);
		if (root1 == root2) return;
		if (sz[root1] < sz[root2]) {
			sz[root2] += sz[root1];
			id[root1] = root2;
		} else {
			sz[root1] += sz[root2];
			id[root2] = root1;
		}
		numComponents--;
	}

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
//import java.math.*;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */

public class Main {

	static int MD= 1000000007 ;
    public static void main(String[] args) throws IOException {
    	OutputStream outputStream = System.out;
        InputReader in = new InputReader();
        PrintWriter out = new PrintWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }

    static int mx=0;
    static boolean[] vis=new boolean[200005];
    static ArrayList<Integer>[] edges;
    static class TaskC {

	    public void solve(int testNumber, InputReader in, PrintWriter out) throws IOException {
	    	int t=1;
	    	while(t-->0) {
	    		int n=in.nextInt();
	    		int m=in.nextInt();
	    		edges=new ArrayList[n];
	    		for(int i=0;i<n;i++) {
	    			edges[i]=new ArrayList<Integer>();
	    		}
	    		vis=new boolean[n];
	    		for(int i=0;i<m;i++) {
	    			int x=in.nextInt();
	    			int y=in.nextInt();
					edges[x].add(y);
					edges[y].add(x);

	    		}
	    		int res=0;
	    		for(int i=0;i<n;i++) {
	    			if(!vis[i]) {
	    				if(i<mx) {
	    					res++;
	    				}
	    				dfs(i);
	    			}
	    		}
	    		out.println(res);

	        }

	    }

    }
    static void dfs(int i) {
 	   vis[i]=true;
 	   mx=Math.max(mx, i);
 	   for(int j:edges[i]) {
 		   if(!vis[j]) {
 			   dfs(j);
 		   }
 	   }

    }

    static class InputReader
    {
        BufferedReader br;
        StringTokenizer st;

        public InputReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }

    }
    static void sort(int[] a, int low, int high)
    {
        int N = high - low;
        if (N <= 1)
            return;
        int mid = low + N/2;
        sort(a, low, mid);
        sort(a, mid, high);
        int[] temp = new int[N];
        int i = low, j = mid;
        for (int k = 0; k < N; k++)
        {
            if (i == mid)
                temp[k] = a[j++];
            else if (j == high)
                temp[k] = a[i++];
            else if (a[j]<a[i])
                temp[k] = a[j++];
            else
                temp[k] = a[i++];
        }
        for (int k = 0; k < N; k++)
            a[low + k] = temp[k];
    }
    static void lsort(long[] a, int low, int high)
    {
        int N = high - low;
        if (N <= 1)
            return;
        int mid = low + N/2;
        lsort(a, low, mid);
        lsort(a, mid, high);
        long[] temp = new long[N];
        int i = low, j = mid;
        for (int k = 0; k < N; k++)
        {
            if (i == mid)
                temp[k] = a[j++];
            else if (j == high)
                temp[k] = a[i++];
            else if (a[j]<a[i])
                temp[k] = a[j++];
            else
                temp[k] = a[i++];
        }
        for (int k = 0; k < N; k++)
            a[low + k] = temp[k];
    }
    public static long fexp(long x, long y, long p) {
        long res = 1;

        x = x % p;

        while (y > 0)
        {

            if((y & 1)==1)
                res = (res * x) % p;

            y = y >> 1;
            x = (x * x) % p;
        }
        return res;

    }
    static int gcd(int a, int b)
    {
        if (b == 0)
            return a;
        return gcd(b, a % b);

    }
    static long lgcd(long a, long b)
    {
        if (b == 0)
            return a;
        return lgcd(b, a % b);

    }

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
//import java.math.*;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */

public class Main {

	static int MD= 1000000007 ;
    public static void main(String[] args) throws IOException {
    	OutputStream outputStream = System.out;
        InputReader in = new InputReader();
        PrintWriter out = new PrintWriter(outputStream);
        TaskC solver = new TaskC();
        solver.solve(1, in, out);
        out.close();
    }

    static int mx=0;
    static boolean[] vis=new boolean[200005];
    static ArrayList<Integer>[] edges;
    static class TaskC {

	    public void solve(int testNumber, InputReader in, PrintWriter out) throws IOException {
	    	int t=1;
	    	while(t-->0) {
	    		int n=in.nextInt();
	    		int m=in.nextInt();
	    		edges=new ArrayList[n];
	    		for(int i=0;i<n;i++) {
	    			edges[i]=new ArrayList<Integer>();
	    		}
	    		vis=new boolean[n];
	    		for(int i=0;i<m;i++) {
	    			int x=in.nextInt()-1;
	    			int y=in.nextInt()-1;
					edges[x].add(y);
					edges[y].add(x);

	    		}
	    		int res=0;
	    		for(int i=0;i<n;i++) {
	    			if(!vis[i]) {
	    				if(i<mx) {
	    					res++;
	    				}
	    				dfs(i);
	    			}
	    		}
	    		out.println(res);

	        }

	    }

    }
    static void dfs(int i) {
 	   vis[i]=true;
 	   mx=Math.max(mx, i);
 	   for(int j:edges[i]) {
 		   if(!vis[j]) {
 			   dfs(j);
 		   }
 	   }

    }

    static class InputReader
    {
        BufferedReader br;
        StringTokenizer st;

        public InputReader()
        {
            br = new BufferedReader(new
                     InputStreamReader(System.in));
        }

        String next()
        {
            while (st == null || !st.hasMoreElements())
            {
                try
                {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException  e)
                {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt()
        {
            return Integer.parseInt(next());
        }

        long nextLong()
        {
            return Long.parseLong(next());
        }

        double nextDouble()
        {
            return Double.parseDouble(next());
        }

        String nextLine()
        {
            String str = "";
            try
            {
                str = br.readLine();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            return str;
        }

    }
    static void sort(int[] a, int low, int high)
    {
        int N = high - low;
        if (N <= 1)
            return;
        int mid = low + N/2;
        sort(a, low, mid);
        sort(a, mid, high);
        int[] temp = new int[N];
        int i = low, j = mid;
        for (int k = 0; k < N; k++)
        {
            if (i == mid)
                temp[k] = a[j++];
            else if (j == high)
                temp[k] = a[i++];
            else if (a[j]<a[i])
                temp[k] = a[j++];
            else
                temp[k] = a[i++];
        }
        for (int k = 0; k < N; k++)
            a[low + k] = temp[k];
    }
    static void lsort(long[] a, int low, int high)
    {
        int N = high - low;
        if (N <= 1)
            return;
        int mid = low + N/2;
        lsort(a, low, mid);
        lsort(a, mid, high);
        long[] temp = new long[N];
        int i = low, j = mid;
        for (int k = 0; k < N; k++)
        {
            if (i == mid)
                temp[k] = a[j++];
            else if (j == high)
                temp[k] = a[i++];
            else if (a[j]<a[i])
                temp[k] = a[j++];
            else
                temp[k] = a[i++];
        }
        for (int k = 0; k < N; k++)
            a[low + k] = temp[k];
    }
    public static long fexp(long x, long y, long p) {
        long res = 1;

        x = x % p;

        while (y > 0)
        {

            if((y & 1)==1)
                res = (res * x) % p;

            y = y >> 1;
            x = (x * x) % p;
        }
        return res;

    }
    static int gcd(int a, int b)
    {
        if (b == 0)
            return a;
        return gcd(b, a % b);

    }
    static long lgcd(long a, long b)
    {
        if (b == 0)
            return a;
        return lgcd(b, a % b);

    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class P1253D
{
    private static int[] arr, size, min, max;
    private static boolean[] visited;
    private static LinkedList<Integer>[] graph;
    public static void main(String[] args) throws IOException
    {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(in.readLine());
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());

        graph = new LinkedList[n];
        arr = new int[n];
        size = new int[n];
        min = new int[n];
        max = new int[n];
        for (int i = 0; i < n; i++)
        {
            graph[i] = new LinkedList<>();
            arr[i] = i;
            size[i] = 1;
            min[i] = i;
            max[i] = i;
        }

        for (int i = 0; i < m; i++)
        {
            st = new StringTokenizer(in.readLine());
            int a = Integer.parseInt(st.nextToken()) - 1;
            int b = Integer.parseInt(st.nextToken()) - 1;
            graph[a].add(b);
            graph[b].add(a);
        }

        int numEdges = 0;
        visited = new boolean[n];
        for (int i = 0; i < n; i++)
        {
            if (!visited[i])
            {
                dfs(i);
                for (int j = min[i]; j <= max[i]; j++)
                {
                    if (root(i) != root(j))
                    {
                        numEdges++;
                        union(i, j);
                        if (!visited[j])
                            dfs(j);
                    }
                }
            }
        }
        System.out.println(numEdges);
    }

    private static void dfs(int v)
    {
        visited[v] = true;
        for (int u : graph[v])
        {
            if (!visited[u])
            {
                union(v, u);
                dfs(u);
            }
        }
    }

    private static void union(int a, int b)
    {
        int ra = root(a);
        int rb = root(b);
        if (size[ra] < size[rb])
        {
            arr[ra] = arr[rb];
            size[rb] += size[ra];
        }
        else
        {
            arr[rb] = arr[ra];
            size[ra] += size[rb];
        }
        min[ra] = Math.min(min[ra], min[rb]);
        min[rb] = Math.min(min[ra], min[rb]);
        max[ra] = Math.max(max[ra], max[rb]);
        max[rb] = Math.max(max[ra], max[rb]);
    }

    private static int root(int i)
    {
        while (arr[i] != i)
        {
            arr[i] = arr[arr[i]];
            i = arr[i];
        }
        return i;
    }
}


import java.io.*;
import java.util.*;

public class D
{
	public static void solve(int n, int[] a, int m, FastIO io)
	{
		long[] dp = new long[n];
		long[] sum = new long[n];

		Arrays.sort(a);

		for (int i = 0; i < m; i++)
			sum[i] = a[i];

		for (int i = m; i < n; i++)
			sum[i] = a[i] + sum[i - m];

		dp[0] = a[0];

		for (int i = 1; i < n; i++)
			dp[i] = dp[i - 1] + sum[i];

		for (long i : dp)
			io.print(i + " ");

		io.println();
	}

	static int[] parent;
	static int[] max;

	public static void union(int a, int b)
	{
		int u = Math.min(a, b);
		int v = Math.max(a, b);

		u = getParent(u);
		v = getParent(v);

		a = Math.min(u, v);
		b = Math.max(u, v);

		parent[b] = a;
		max[a] = Math.max(max[a], max[b]);
	}

	public static int getParent(int u)
	{
		if (parent[u] == u)
			return u;
		return parent[u] = getParent(parent[u]);
	}

	public static void main(String[] args)
	{
		FastIO io = new FastIO();

		int n = io.nextInt();
		int m = io.nextInt();

		parent = new int[n];
		max = new int[n];

		for (int i = 0; i < n; i++)
		{
			parent[i] = i;
			max[i] = i;
		}

		for (int i = 0; i < m; i++)
			union(io.nextInt() - 1, io.nextInt() - 1);

		// io.println(Arrays.toString(parent));
		// io.println(Arrays.toString(max));

		int count = 0;
		for (int i = 0; i < n - 1; i++)
		{
			if (getParent(i) != getParent(i + 1))
			{
				if (max[getParent(i)] > i + 1)
				{
					union(i, i + 1);
					count++;
					// io.println("join " + (i + 1) + " and " + (i + 2));
				}
			}
		}

		// io.println(Arrays.toString(parent));
		// io.println(Arrays.toString(max));

		io.println(count);

		// HashMap<Integer, HashSet<Integer>> adj = new HashMap<>();

		// for (int i = 0; i < n; i++)
		// 	adj.put(i, new HashSet<>());

		// for (int i = 0; i < m; i++)
		// {
		// 	int u = io.nextInt() - 1;
		// 	int v = io.nextInt() - 1;

		// 	adj.get(u).add(v);
		// 	adj.get(v).add(u);
		// }

		// boolean[] used = new boolean[n];

		// for (int i = 0; i < n; i++)
		// {
		// 	if (!used[i])
		// 	{
		// 		TreeSet<Integer> t = new TreeSet<>();
		// 		dfs(i, adj, t, used);

		// 		for (int k : t)
		// 			io.print(k + " ");
		// 		io.println();
		// 	}
		// }

		io.close();
	}

	public static void dfs(int u, HashMap<Integer, HashSet<Integer>> adj, TreeSet<Integer> comp, boolean[] used)
	{
		comp.add(u + 1);

		for (int v : adj.get(u))
		{
			if (used[v])
				continue;

			used[v] = true;
			dfs(v, adj, comp, used);
		}
	}
}

class FastIO extends PrintWriter
{
	BufferedReader r;
	StringTokenizer st = new StringTokenizer("");

	FastIO()
	{
		super(System.out);
		r = new BufferedReader(new InputStreamReader(System.in));
	}

	public String next()
	{
		while (!st.hasMoreTokens())
		{
			try
			{
				st = new StringTokenizer(r.readLine());
			}
			catch(Exception e) {}
		}

		return st.nextToken();
	}

	public int nextInt()
	{
		return Integer.parseInt(next());
	}
}


import java.util.*;
import java.io.*;
public class EdD {

	public static void main(String[] args) throws Exception{
		int num = 998244353;

		// TODO Auto-generated method stub
 		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
 		PrintWriter out = new PrintWriter(System.out);
 		StringTokenizer st = new StringTokenizer(bf.readLine());
 		int n = Integer.parseInt(st.nextToken());
 		int m = Integer.parseInt(st.nextToken());
 		Map<Integer,ArrayList<Integer>> graph = new HashMap<Integer, ArrayList<Integer>>();
 		for(int j = 1;j<=n;j++){
 			graph.put(j,  new ArrayList<Integer>());
 		}
 		for(int j = 0;j<m;j++){
 			StringTokenizer st1 = new StringTokenizer(bf.readLine());
 			int v1 = Integer.parseInt(st1.nextToken());
 			int v2 = Integer.parseInt(st1.nextToken());
 			graph.get(v1).add(v2);
 			graph.get(v2).add(v1);
 		}
 		int[] groups = new int[n+1];
 		int groupcount = 1;
 		Set<Integer> seen = new HashSet<Integer>();
 		for(int j = 1;j<=n;j++){
 			if (!seen.contains(j)){
 				Queue<Integer> bfs = new LinkedList<Integer>();
 				bfs.add(j);
 				while(!bfs.isEmpty()){
 					int vertex = bfs.remove();
 					for(int child : graph.get(vertex)){
 						if (!seen.contains(child))
 							bfs.add(child);
 					}
 					seen.add(vertex);
 					groups[vertex] = groupcount;
 				}
 				groupcount++;
 			}
 		}
 		int[] start = new int[groupcount+1];
 		int[] end = new int[groupcount+1];
 		for(int j = 1;j<=n;j++){
 			if (start[groups[j]] == 0)
 				start[groups[j]] = j;
 			end[groups[j]] = j;
 		}

 		ArrayList<StartEnd> array = new ArrayList<StartEnd>();
 		for(int j = 1;j<=groupcount;j++){
 			array.add(new StartEnd(j, true, start[j]));
 		}
 		for(int j =1;j<=groupcount;j++){
 			array.add(new StartEnd(j, false, end[j]));
 		}
 		Collections.sort(array);
 		Set<Integer> s = new HashSet<Integer>();
 		int count = 0;
 		for(int j = 0;j<array.size();j++){
 			if (array.get(j).isStartEnd()){
 				s.add(array.get(j).getGroup());
 			}
 			else{
 				s.remove(array.get(j).getGroup());
 			}
 			if (s.isEmpty())
 				count++;
 		}

 		out.println(groupcount-count);

 		out.close();

 	}
	static class StartEnd implements Comparable<StartEnd>{
		private int group;
		private boolean startEnd; //true = start end = false;
		private int index;
		public StartEnd(int group, boolean startEnd, int index){
			this.group = group;
			this.startEnd = startEnd;
			this.index = index;
		}
		public int getIndex() {
			return index;
		}
		public void setIndex(int index) {
			this.index = index;
		}
		public int getGroup() {
			return group;
		}
		public void setGroup(int group) {
			this.group = group;
		}
		public boolean isStartEnd() {
			return startEnd;
		}
		public void setStartEnd(boolean startEnd) {
			this.startEnd = startEnd;
		}
		public int compareTo(StartEnd other){
			return index - other.index;
		}
	}
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


/**
 * Date: 16 Nov, 2019
 * Link: https://codeforces.com/contest/1253/problem/D
 *
 * @author Prasad Chaudhari
 * @linkedIn: https://www.linkedin.com/in/prasad-chaudhari-841655a6/
 * @git: https://github.com/Prasad-Chaudhari
 */
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class D_1253 {

    public static void main(String[] args) throws IOException {
        // TODO code application logic here
        FastIO in = new FastIO();
        int n = in.ni();
        int m = in.ni();
        int adja[][] = in.gg(n, m);
        FastUnionFind uf = new FastUnionFind(n);
        for (int i = 1; i <= n; i++) {
            for (int j : adja[i]) {
                uf.union(i, j);
            }
        }
        Map<Integer, Integer> map = new Hashtable<>();
        for (int i = 1; i <= n; i++) {
            map.put(uf.find(i), Math.max(map.getOrDefault(uf.find(i), 0), i));
        }
        boolean b[] = new boolean[n + 1];
        int count = 0;
        for (int i = 1; i <= n; i++) {
            if (!b[i]) {
                int max = map.get(uf.find(i));
                for (int j = i + 1; j <= max; j++) {
                    if (uf.find(i) != uf.find(j)) {
                        int mm = Math.max(map.get(uf.find(i)), map.get(uf.find(j)));
                        uf.union(i, j);
                        map.put(uf.find(i), mm);
                        mm = Math.max(max, mm);
                        count++;
                    }
                    b[j] = true;
                }
            }
        }
        System.out.println(count);
        in.bw.flush();
    }

    static public class FastUnionFind {

        int noOfComponents, n;
        private int[] parent, rank;

        public FastUnionFind(int n) {
            this.n = n;
            this.noOfComponents = n;
            parent = new int[n + 1];
            rank = new int[n + 1];
            for (int i = 0; i <= n; i++) {
                parent[i] = i;
                rank[i] = 1;
            }
        }

        public int find(int p) {
            if (parent[p] == p) {
                return p;
            } else {
                return find(parent[p]);
            }
        }

        public void union(int a, int b) {
            a = find(a);
            b = find(b);
            if (a != b) {
                if (rank[a] > rank[b]) {
                    parent[b] = a;
                } else if (rank[b] > rank[a]) {
                    parent[a] = b;
                } else {
                    parent[b] = a;
                    rank[a]++;
                }
                noOfComponents--;
            }
        }
    }

    static class Data implements Comparable<Data> {

        int a, b;

        public Data(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int compareTo(Data o) {
            if (a == o.a) {
                return Integer.compare(b, o.b);
            }
            return Integer.compare(a, o.a);
        }

        public static void sort(int a[]) {
            Data d[] = new Data[a.length];
            for (int i = 0; i < a.length; i++) {
                d[i] = new Data(a[i], 0);
            }
            Arrays.sort(d);
            for (int i = 0; i < a.length; i++) {
                a[i] = d[i].a;
            }
        }
    }

    static class FastIO {

        private final BufferedReader br;
        private final BufferedWriter bw;
        private String s[];
        private int index;

        public FastIO() throws IOException {
            br = new BufferedReader(new InputStreamReader(System.in));
            bw = new BufferedWriter(new OutputStreamWriter(System.out, "UTF-8"));
            s = br.readLine().split(" ");
            index = 0;
        }

        public int ni() throws IOException {
            return Integer.parseInt(nextToken());
        }

        public double nd() throws IOException {
            return Double.parseDouble(nextToken());
        }

        public long nl() throws IOException {
            return Long.parseLong(nextToken());
        }

        public String next() throws IOException {
            return nextToken();
        }

        public String nli() throws IOException {
            try {
                return br.readLine();
            } catch (IOException ex) {

            }
            return null;
        }

        public int[] gia(int n) throws IOException {
            int a[] = new int[n];
            for (int i = 0; i < n; i++) {
                a[i] = ni();
            }
            return a;
        }

        public int[] gia(int n, int start, int end) throws IOException {
            validate(n, start, end);
            int a[] = new int[n];
            for (int i = start; i < end; i++) {
                a[i] = ni();
            }
            return a;
        }

        public double[] gda(int n) throws IOException {
            double a[] = new double[n];
            for (int i = 0; i < n; i++) {
                a[i] = nd();
            }
            return a;
        }

        public double[] gda(int n, int start, int end) throws IOException {
            validate(n, start, end);
            double a[] = new double[n];
            for (int i = start; i < end; i++) {
                a[i] = nd();
            }
            return a;
        }

        public long[] gla(int n) throws IOException {
            long a[] = new long[n];
            for (int i = 0; i < n; i++) {
                a[i] = nl();
            }
            return a;
        }

        public long[] gla(int n, int start, int end) throws IOException {
            validate(n, start, end);
            long a[] = new long[n];
            for (int i = start; i < end; i++) {
                a[i] = nl();
            }
            return a;
        }

        public int[][][] gwtree(int n) throws IOException {
            int m = n - 1;
            int adja[][] = new int[n + 1][];
            int weight[][] = new int[n + 1][];
            int from[] = new int[m];
            int to[] = new int[m];
            int count[] = new int[n + 1];
            int cost[] = new int[n + 1];
            for (int i = 0; i < m; i++) {
                from[i] = i + 1;
                to[i] = ni();
                cost[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
                weight[i] = new int[count[i]];
            }
            for (int i = 0; i < m; i++) {
                adja[from[i]][count[from[i]] - 1] = to[i];
                adja[to[i]][count[to[i]] - 1] = from[i];
                weight[from[i]][count[from[i]] - 1] = cost[i];
                weight[to[i]][count[to[i]] - 1] = cost[i];
                count[from[i]]--;
                count[to[i]]--;
            }
            return new int[][][] { adja, weight };
        }

        public int[][][] gwg(int n, int m) throws IOException {
            int adja[][] = new int[n + 1][];
            int weight[][] = new int[n + 1][];
            int from[] = new int[m];
            int to[] = new int[m];
            int count[] = new int[n + 1];
            int cost[] = new int[n + 1];
            for (int i = 0; i < m; i++) {
                from[i] = ni();
                to[i] = ni();
                cost[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
                weight[i] = new int[count[i]];
            }
            for (int i = 0; i < m; i++) {
                adja[from[i]][count[from[i]] - 1] = to[i];
                adja[to[i]][count[to[i]] - 1] = from[i];
                weight[from[i]][count[from[i]] - 1] = cost[i];
                weight[to[i]][count[to[i]] - 1] = cost[i];
                count[from[i]]--;
                count[to[i]]--;
            }
            return new int[][][] { adja, weight };
        }

        public int[][] gtree(int n) throws IOException {
            int adja[][] = new int[n + 1][];
            int from[] = new int[n - 1];
            int to[] = new int[n - 1];
            int count[] = new int[n + 1];
            for (int i = 0; i < n - 1; i++) {
                from[i] = i + 1;
                to[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
            }
            for (int i = 0; i < n - 1; i++) {
                adja[from[i]][--count[from[i]]] = to[i];
                adja[to[i]][--count[to[i]]] = from[i];
            }
            return adja;
        }

        public int[][] gg(int n, int m) throws IOException {
            int adja[][] = new int[n + 1][];
            int from[] = new int[m];
            int to[] = new int[m];
            int count[] = new int[n + 1];
            for (int i = 0; i < m; i++) {
                from[i] = ni();
                to[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
            }
            for (int i = 0; i < m; i++) {
                adja[from[i]][--count[from[i]]] = to[i];
                adja[to[i]][--count[to[i]]] = from[i];
            }
            return adja;
        }

        public void print(String s) throws IOException {
            bw.write(s);
        }

        public void println(String s) throws IOException {
            bw.write(s);
            bw.newLine();
        }

        public void print(int s) throws IOException {
            bw.write(s + "");
        }

        public void println(int s) throws IOException {
            bw.write(s + "");
            bw.newLine();
        }

        public void print(long s) throws IOException {
            bw.write(s + "");
        }

        public void println(long s) throws IOException {
            bw.write(s + "");
            bw.newLine();
        }

        public void print(double s) throws IOException {
            bw.write(s + "");
        }

        public void println(double s) throws IOException {
            bw.write(s + "");
            bw.newLine();
        }

        private String nextToken() throws IndexOutOfBoundsException, IOException {
            if (index == s.length) {
                s = br.readLine().split(" ");
                index = 0;
            }
            return s[index++];
        }

        private void validate(int n, int start, int end) {
            if (start < 0 || end >= n) {
                throw new IllegalArgumentException();
            }
        }
    }
}


/**
 * Date: 16 Nov, 2019
 * Link: https://codeforces.com/contest/1253/problem/D
 *
 * @author Prasad Chaudhari
 * @linkedIn: https://www.linkedin.com/in/prasad-chaudhari-841655a6/
 * @git: https://github.com/Prasad-Chaudhari
 */
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class D_1253 {

    public static void main(String[] args) throws IOException {
        // TODO code application logic here
        FastIO in = new FastIO();
        int n = in.ni();
        int m = in.ni();
        int adja[][] = in.gg(n, m);
        FastUnionFind uf = new FastUnionFind(n);
        for (int i = 1; i <= n; i++) {
            for (int j : adja[i]) {
                uf.union(i, j);
            }
        }
        Map<Integer, Integer> map = new Hashtable<>();
        for (int i = 1; i <= n; i++) {
            map.put(uf.find(i), Math.max(map.getOrDefault(uf.find(i), 0), i));
        }
        boolean b[] = new boolean[n + 1];
        int count = 0;
        for (int i = 1; i <= n; i++) {
            if (!b[i]) {
                int max = map.get(uf.find(i));
                for (int j = i; j <= max; j++) {
                    if (uf.find(i) != uf.find(j)) {
                        int mm = Math.max(map.get(uf.find(i)), map.get(uf.find(j)));
                        uf.union(i, j);
                        map.put(uf.find(i), mm);
                        max = Math.max(max, mm);
                        count++;
                    }
                    b[j] = true;
                }
            }
        }
        System.out.println(count);
        in.bw.flush();
    }

    static public class FastUnionFind {

        int noOfComponents, n;
        private int[] parent, rank;

        public FastUnionFind(int n) {
            this.n = n;
            this.noOfComponents = n;
            parent = new int[n + 1];
            rank = new int[n + 1];
            for (int i = 0; i <= n; i++) {
                parent[i] = i;
                rank[i] = 1;
            }
        }

        public int find(int p) {
            if (parent[p] == p) {
                return p;
            } else {
                return find(parent[p]);
            }
        }

        public void union(int a, int b) {
            a = find(a);
            b = find(b);
            if (a != b) {
                if (rank[a] > rank[b]) {
                    parent[b] = a;
                } else if (rank[b] > rank[a]) {
                    parent[a] = b;
                } else {
                    parent[b] = a;
                    rank[a]++;
                }
                noOfComponents--;
            }
        }
    }

    static class Data implements Comparable<Data> {

        int a, b;

        public Data(int a, int b) {
            this.a = a;
            this.b = b;
        }

        @Override
        public int compareTo(Data o) {
            if (a == o.a) {
                return Integer.compare(b, o.b);
            }
            return Integer.compare(a, o.a);
        }

        public static void sort(int a[]) {
            Data d[] = new Data[a.length];
            for (int i = 0; i < a.length; i++) {
                d[i] = new Data(a[i], 0);
            }
            Arrays.sort(d);
            for (int i = 0; i < a.length; i++) {
                a[i] = d[i].a;
            }
        }
    }

    static class FastIO {

        private final BufferedReader br;
        private final BufferedWriter bw;
        private String s[];
        private int index;

        public FastIO() throws IOException {
            br = new BufferedReader(new InputStreamReader(System.in));
            bw = new BufferedWriter(new OutputStreamWriter(System.out, "UTF-8"));
            s = br.readLine().split(" ");
            index = 0;
        }

        public int ni() throws IOException {
            return Integer.parseInt(nextToken());
        }

        public double nd() throws IOException {
            return Double.parseDouble(nextToken());
        }

        public long nl() throws IOException {
            return Long.parseLong(nextToken());
        }

        public String next() throws IOException {
            return nextToken();
        }

        public String nli() throws IOException {
            try {
                return br.readLine();
            } catch (IOException ex) {

            }
            return null;
        }

        public int[] gia(int n) throws IOException {
            int a[] = new int[n];
            for (int i = 0; i < n; i++) {
                a[i] = ni();
            }
            return a;
        }

        public int[] gia(int n, int start, int end) throws IOException {
            validate(n, start, end);
            int a[] = new int[n];
            for (int i = start; i < end; i++) {
                a[i] = ni();
            }
            return a;
        }

        public double[] gda(int n) throws IOException {
            double a[] = new double[n];
            for (int i = 0; i < n; i++) {
                a[i] = nd();
            }
            return a;
        }

        public double[] gda(int n, int start, int end) throws IOException {
            validate(n, start, end);
            double a[] = new double[n];
            for (int i = start; i < end; i++) {
                a[i] = nd();
            }
            return a;
        }

        public long[] gla(int n) throws IOException {
            long a[] = new long[n];
            for (int i = 0; i < n; i++) {
                a[i] = nl();
            }
            return a;
        }

        public long[] gla(int n, int start, int end) throws IOException {
            validate(n, start, end);
            long a[] = new long[n];
            for (int i = start; i < end; i++) {
                a[i] = nl();
            }
            return a;
        }

        public int[][][] gwtree(int n) throws IOException {
            int m = n - 1;
            int adja[][] = new int[n + 1][];
            int weight[][] = new int[n + 1][];
            int from[] = new int[m];
            int to[] = new int[m];
            int count[] = new int[n + 1];
            int cost[] = new int[n + 1];
            for (int i = 0; i < m; i++) {
                from[i] = i + 1;
                to[i] = ni();
                cost[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
                weight[i] = new int[count[i]];
            }
            for (int i = 0; i < m; i++) {
                adja[from[i]][count[from[i]] - 1] = to[i];
                adja[to[i]][count[to[i]] - 1] = from[i];
                weight[from[i]][count[from[i]] - 1] = cost[i];
                weight[to[i]][count[to[i]] - 1] = cost[i];
                count[from[i]]--;
                count[to[i]]--;
            }
            return new int[][][] { adja, weight };
        }

        public int[][][] gwg(int n, int m) throws IOException {
            int adja[][] = new int[n + 1][];
            int weight[][] = new int[n + 1][];
            int from[] = new int[m];
            int to[] = new int[m];
            int count[] = new int[n + 1];
            int cost[] = new int[n + 1];
            for (int i = 0; i < m; i++) {
                from[i] = ni();
                to[i] = ni();
                cost[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
                weight[i] = new int[count[i]];
            }
            for (int i = 0; i < m; i++) {
                adja[from[i]][count[from[i]] - 1] = to[i];
                adja[to[i]][count[to[i]] - 1] = from[i];
                weight[from[i]][count[from[i]] - 1] = cost[i];
                weight[to[i]][count[to[i]] - 1] = cost[i];
                count[from[i]]--;
                count[to[i]]--;
            }
            return new int[][][] { adja, weight };
        }

        public int[][] gtree(int n) throws IOException {
            int adja[][] = new int[n + 1][];
            int from[] = new int[n - 1];
            int to[] = new int[n - 1];
            int count[] = new int[n + 1];
            for (int i = 0; i < n - 1; i++) {
                from[i] = i + 1;
                to[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
            }
            for (int i = 0; i < n - 1; i++) {
                adja[from[i]][--count[from[i]]] = to[i];
                adja[to[i]][--count[to[i]]] = from[i];
            }
            return adja;
        }

        public int[][] gg(int n, int m) throws IOException {
            int adja[][] = new int[n + 1][];
            int from[] = new int[m];
            int to[] = new int[m];
            int count[] = new int[n + 1];
            for (int i = 0; i < m; i++) {
                from[i] = ni();
                to[i] = ni();
                count[from[i]]++;
                count[to[i]]++;
            }
            for (int i = 0; i <= n; i++) {
                adja[i] = new int[count[i]];
            }
            for (int i = 0; i < m; i++) {
                adja[from[i]][--count[from[i]]] = to[i];
                adja[to[i]][--count[to[i]]] = from[i];
            }
            return adja;
        }

        public void print(String s) throws IOException {
            bw.write(s);
        }

        public void println(String s) throws IOException {
            bw.write(s);
            bw.newLine();
        }

        public void print(int s) throws IOException {
            bw.write(s + "");
        }

        public void println(int s) throws IOException {
            bw.write(s + "");
            bw.newLine();
        }

        public void print(long s) throws IOException {
            bw.write(s + "");
        }

        public void println(long s) throws IOException {
            bw.write(s + "");
            bw.newLine();
        }

        public void print(double s) throws IOException {
            bw.write(s + "");
        }

        public void println(double s) throws IOException {
            bw.write(s + "");
            bw.newLine();
        }

        private String nextToken() throws IndexOutOfBoundsException, IOException {
            if (index == s.length) {
                s = br.readLine().split(" ");
                index = 0;
            }
            return s[index++];
        }

        private void validate(int n, int start, int end) {
            if (start < 0 || end >= n) {
                throw new IllegalArgumentException();
            }
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

import java.util.*;

public class Main {
static class UnionFind {
    List<Integer> Parent;
    UnionFind(int N) {
        Parent = new ArrayList<Integer>();
        Integer[] values = new Integer[N];
        Arrays.fill(values, -1);
        Parent.addAll(Arrays.asList(values));
    }
    int root(int A) {
        if (Parent.get(A) < 0)
            return A;
        int root = root(Parent.get(A));
        Parent.set(A, root);
        return root;
    }
    int size(int A) {
        return -Parent.get(root(A));
    }

    boolean connect(int A, int B) {
        A = root(A);
        B = root(B);
        if (A == B) {
            return false;
        }

        // if (size(A) < size(B)) {
        //     int temp = A;
        //     A = B;
        //     B = temp;
        // }
        if (A<B) {
            int temp = A;
            A = B;
            B = temp;
        }

        Parent.set(A, Parent.get(A) + Parent.get(B));
        Parent.set(B, A);

        return true;
    }
}
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);

        int n = in.nextInt();
        int m = in.nextInt();
        UnionFind uf = new UnionFind(n);
        for (int i=0;i<m;i++) {
            int u = in.nextInt()-1;
            int v = in.nextInt()-1;
            uf.connect(u, v);
        }
        int[] rt = new int[n];
        for (int i=0;i<n;i++) {
            rt[i]=uf.root(i);
        }
        // out.println(Arrays.toString(rt));
        int ans = 0;
        for (int i=1;i<n;i++) {
            if (uf.root(i)<uf.root(i-1)) {
                uf.connect(i, i-1);
                // if (i!=1) {
                //     i-=2;
                // }
                ans++;
            }
        }
        out.println(ans);
        out.close();
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

import java.util.*;

public class Main {
static class UnionFind {
    List<Integer> Parent;
    UnionFind(int N) {
        Parent = new ArrayList<Integer>();
        Integer[] values = new Integer[N];
        Arrays.fill(values, -1);
        Parent.addAll(Arrays.asList(values));
    }
    int root(int A) {
        if (Parent.get(A) < 0)
            return A;
        int root = root(Parent.get(A));
        Parent.set(A, root);
        return root;
    }
    int size(int A) {
        return -Parent.get(root(A));
    }

    boolean connect(int A, int B) {
        A = root(A);
        B = root(B);
        if (A == B) {
            return false;
        }

        if (size(A) < size(B)) {
            int temp = A;
            A = B;
            B = temp;
        }

        Parent.set(A, Parent.get(A) + Parent.get(B));
        Parent.set(B, A);

        return true;
    }
}
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);

        int n = in.nextInt();
        int m = in.nextInt();
        UnionFind uf = new UnionFind(n);
        for (int i=0;i<m;i++) {
            int u = in.nextInt()-1;
            int v = in.nextInt()-1;
            uf.connect(u, v);
        }
        int[] rt = new int[n];
        for (int i=0;i<n;i++) {
            rt[i]=uf.root(i);
        }
        int ans = 0;
        for (int i=1;i<n;i++) {
            if (uf.root(i)<uf.root(i-1)) {
                uf.connect(i, i-1);
                if (i!=1) {
                    i-=2;
                }
                ans++;
            }
        }
        out.println(ans);
        // out.println(Arrays.toString(rt));
        out.close();
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;

import java.util.*;

public class Main {
static class UnionFind {
    List<Integer> Parent;
    UnionFind(int N) {
        Parent = new ArrayList<Integer>();
        Integer[] values = new Integer[N];
        Arrays.fill(values, -1);
        Parent.addAll(Arrays.asList(values));
    }
    int root(int A) {
        if (Parent.get(A) < 0)
            return A;
        int root = root(Parent.get(A));
        Parent.set(A, root);
        return root;
    }
    int size(int A) {
        return -Parent.get(root(A));
    }

    boolean connect(int A, int B) {
        A = root(A);
        B = root(B);
        if (A == B) {
            return false;
        }

        if (size(A) < size(B)) {
            int temp = A;
            A = B;
            B = temp;
        }

        Parent.set(A, Parent.get(A) + Parent.get(B));
        Parent.set(B, A);

        return true;
    }
}
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);

        int n = in.nextInt();
        int m = in.nextInt();
        UnionFind uf = new UnionFind(n);
        for (int i=0;i<m;i++) {
            int u = in.nextInt()-1;
            int v = in.nextInt()-1;
            uf.connect(u, v);
        }
        // int[] rt = new int[n];
        // for (int i=0;i<n;i++) {
        //     rt[i]=uf.root(i);
        // }
        int ans = 0;
        for (int i=1;i<n;i++) {
            if (uf.root(i)<uf.root(i-1)) {
                uf.connect(i, i-1);
                ans++;
            }
        }
        out.println(ans);
        // out.println(Arrays.toString(rt));
        out.close();
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}