/* Rajkin Hossain */

import java.io.*;
import java.util.*;
import static java.lang.Math.*;

public class D {

    FastInput k = new FastInput(System.in);
    //FastInput k = new FastInput("/home/rajkin/Desktop/input.txt");
    FastOutput z = new FastOutput();

    int nodes, edges;

    UnionFind union;

    void startAlgo() {
    	while(edges-->0) {
    		int u = k.nextInt() - 1;
    		int v = k.nextInt() - 1;

    		union.mergeSets(u, v);
    	}

    	int count = 0;
    	int rootNode = 0;

    	while(true) {
    		for(int node = rootNode; node<=union.getMax(rootNode); node++) {
    			if(!union.isSameSet(rootNode, node)) {
    				union.mergeSets(rootNode, node);
    				count++;
    			}
    		}

    		if(union.getMax(rootNode) == nodes-1) {
    			break;
    		}

    		rootNode = union.getMax(rootNode) + 1;
    	}

    	z.println(count);
    }

    void startProgram() {
    	while(k.hasNext()) {

    		nodes = k.nextInt();
    		edges = k.nextInt();

    		union = new UnionFind(nodes);

    		startAlgo();
    	}

    	z.flush();
    	System.exit(0);
    }

    public class UnionFind {

    	int [] parent;
    	int [] rank;
    	int [] setSize;

    	int [] max;

    	int size;
    	int disjointRoots;

    	public UnionFind(int size) {
    		this.size = size;

    		rank = new int[size];
    		parent = new int[size];
    		setSize = new int[size];

    		max = new int[size];

    		for(int i = 0; i<size; i++) {
    			parent[i] = i;

    			max[i] = i;
    		}

    		disjointRoots = size;
    	}

    	int getMax(int x) {
    		return max[findSet(x)];
    	}

    	public void mergeSets(int x, int y) {
    		int PX = findSet(x);
    		int PY = findSet(y);

    		if(PX == PY) return;

    		disjointRoots--;

    		if (rank[PX] > rank[PY]) {
    			parent[PY] = PX;
    			setSize[PX] = setSize[PX] + setSize[PY];

    			max[PX] = Math.max(max[PX], max[PY]);
    		}
    		else {
    			parent[PX] = PY;
    			setSize[PY] = setSize[PX] + setSize[PY];

    			max[PY] = Math.max(max[PX], max[PY]);
    		}

    		if (rank[PX] == rank[PY]) rank[PY] = rank[PY] + 1; // 2 ta rank soman thaka means ekta tree er size barano
    	}

    	public int sizeOfSet(int i) {
    		return setSize[findSet(i)];
    	}

    	public int numOfDisjointSets() {
    		return disjointRoots;
    	}

    	public int findSet(int x){
    		while (x != parent[x]) {
    			x = parent[x];
    		}

    		return parent[x];
    	}

    	public boolean isSameSet(int x, int y) {

    		return findSet(x) == findSet(y);
    	}
    }

    public static void main(String [] args) throws IOException {
        new Thread(null, new Runnable(){
            public void run(){
            	try{
            		new D().startProgram();
            	}
            	catch(Exception e){
            		e.printStackTrace();
            	}
            }
        },"Main",1<<28).start();
    }

    /* MARK: FastInput and FastOutput */

    class FastInput {
        BufferedReader reader;
        StringTokenizer tokenizer;

        FastInput(InputStream stream){
            reader = new BufferedReader(new InputStreamReader(stream));
        }

        FastInput(String path){
            try {
                reader = new BufferedReader(new FileReader(path));
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            tokenizer = null;
        }

        String next() {
            return nextToken();
        }

        String nextLine() {
            try {
                return reader.readLine();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return null;
        }

        boolean hasNext(){
            try {
                return reader.ready();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return false;
        }

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

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

        long nextLong() {
            return Long.valueOf(nextToken());
        }

        int [] getInputIntegerArray(int n) {

        	int [] input = new int[n];

        	for(int i = 0; i<n; i++) {
        		input[i] = nextInt();
        	}

        	return input;
        }

        long [] getInputLongArray(int n) {

        	long [] input = new long[n];
        	for(int i = 0; i<n; i++) {
        		input[i] = nextLong();
        	}

        	return input;
        }

        int [] getInputIntegerArrayOneBasedIndex(int n) {

        	int [] input = new int[n+1];

        	for(int i = 1; i<=n; i++) {
        		input[i] = nextInt();
        	}

        	return input;
        }

        long [] getInputLongArrayOneBasedIndex(int n) {

        	long [] input = new long[n+1];

        	for(int i = 1; i<=n; i++) {
        		input[i] = nextLong();
        	}

        	return input;
        }
    }

    class FastOutput extends PrintWriter {
		FastOutput() {
			super(new BufferedOutputStream(System.out));
		}

		public void debug(Object...obj) {
		    System.err.println(Arrays.deepToString(obj));
		}
    }
}


// package Quarantine;

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

public class HarmoniusGraph {
    public static int findParent(int u,int parent[][]){
        if(parent[u][0]==u){
            return u;
        }
        int par=findParent(parent[u][0],parent);
        parent[u][0]=par;
        return par;
    }
    public static void union(int u,int v,int parent[][],int size[]){
        int par1=findParent(u,parent);
        int par2=findParent(v,parent);
        if(par1!=par2){
            if(size[par1]<size[par2]){
                size[par2]+=size[par1];
                parent[par1][0]=par2;
                parent[par2][1]=Math.min(parent[par1][1],parent[par2][1]);
                parent[par2][2]=Math.max(parent[par1][2],parent[par2][2]);
            }
            else{
                size[par1]+=size[par2];
                parent[par2][0]=par1;
                parent[par1][1]=Math.min(parent[par1][1],parent[par2][1]);
                parent[par1][2]=Math.max(parent[par1][2],parent[par2][2]);
            }
        }
    }
    public static void main(String[] args)throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.parseInt(st.nextToken());
        int m=Integer.parseInt(st.nextToken());
        int parent[][]=new int[n+1][3];
        int size[]=new int[n+1];
        for(int i=1;i<=n;i++){
            parent[i][0]=parent[i][1]=parent[i][2]=i;
            size[i]=1;
        }
        for(int i=1;i<=m;i++){
            st=new StringTokenizer(br.readLine());
            int u=Integer.parseInt(st.nextToken());
            int v=Integer.parseInt(st.nextToken());
            union(u,v,parent,size);
        }
        int count=0;
        for(int i=1;i<=n;){
            int par=findParent(i,parent);
//            System.out.println(i);
            int s=size[par];
            int min=parent[par][1];
            int max=parent[par][2];
            int reqd=max-min+1;
//            System.out.println(s+" "+reqd);
            if(s==reqd){
                i++;
            }
            else{
                for(int j=i+1;j<=max;j++){
                    if(findParent(i,parent)!=findParent(j,parent)){
                        count++;
                        union(i,j,parent,size);
                    }
                }
                i=max;
            }
        }
        System.out.println(count);
    }
}


// package Quarantine;

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

public class HarmoniusGraph {
    public static int findParent(int u,int parent[][]){
        if(parent[u][0]==u){
            return u;
        }
        int par=findParent(parent[u][0],parent);
        parent[u][0]=par;
        return par;
    }
    public static void union(int u,int v,int parent[][],int size[]){
        int par1=findParent(u,parent);
        int par2=findParent(v,parent);
        if(size[par1]<size[par2]){
            size[par2]+=size[par1];
            parent[par1][0]=par2;
            parent[par2][1]=Math.min(parent[par1][1],parent[par2][1]);
            parent[par2][2]=Math.max(parent[par1][2],parent[par2][2]);
        }
        else{
            size[par1]+=size[par2];
            parent[par2][0]=par1;
            parent[par1][1]=Math.min(parent[par1][1],parent[par2][1]);
            parent[par1][2]=Math.max(parent[par1][2],parent[par2][2]);
        }
    }
    public static void main(String[] args)throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.parseInt(st.nextToken());
        int m=Integer.parseInt(st.nextToken());
        int parent[][]=new int[n+1][3];
        int size[]=new int[n+1];
        for(int i=1;i<=n;i++){
            parent[i][0]=parent[i][1]=parent[i][2]=i;
            size[i]=1;
        }
        for(int i=1;i<=m;i++){
            st=new StringTokenizer(br.readLine());
            int u=Integer.parseInt(st.nextToken());
            int v=Integer.parseInt(st.nextToken());
            union(u,v,parent,size);
        }
        int count=0;
        for(int i=1;i<=n;){
            int par=findParent(i,parent);
            int s=size[par];
            int min=parent[par][1];
            int max=parent[par][2];
            int reqd=max-min+1;
            if(s==reqd){
                i++;
            }
            else{
                for(int j=i+1;j<=max;j++){
                    if(findParent(i,parent)!=findParent(j,parent)){
                        count++;
                        union(i,j,parent,size);
                    }
                }
                i=max+1;
            }
        }
        System.out.println(count);
    }
}


// package Quarantine;

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

public class HarmoniusGraph {
    public static int findParent(int u,int parent[][]){
        if(parent[u][0]==u){
            return u;
        }
        int par=findParent(parent[u][0],parent);
        parent[u][0]=par;
        return par;
    }
    public static void union(int u,int v,int parent[][],int size[]){
        int par1=findParent(u,parent);
        int par2=findParent(v,parent);
        if(size[par1]<size[par2]){
            size[par2]+=size[par1];
            parent[par1][0]=par2;
            parent[par2][1]=Math.min(parent[par1][1],parent[par2][1]);
            parent[par2][2]=Math.max(parent[par1][2],parent[par2][2]);
        }
        else{
            size[par1]+=size[par2];
            parent[par2][0]=par1;
            parent[par1][1]=Math.min(parent[par1][1],parent[par2][1]);
            parent[par1][2]=Math.max(parent[par1][2],parent[par2][2]);
        }
    }
    public static void main(String[] args)throws IOException {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(br.readLine());
        int n=Integer.parseInt(st.nextToken());
        int m=Integer.parseInt(st.nextToken());
        int parent[][]=new int[n+1][3];
        int size[]=new int[n+1];
        for(int i=1;i<=n;i++){
            parent[i][0]=parent[i][1]=parent[i][2]=i;
            size[i]=1;
        }
        for(int i=1;i<=m;i++){
            st=new StringTokenizer(br.readLine());
            int u=Integer.parseInt(st.nextToken());
            int v=Integer.parseInt(st.nextToken());
            union(u,v,parent,size);
        }
        int count=0;
        for(int i=1;i<=n;){
            int par=findParent(i,parent);
            int s=size[par];
            int min=parent[par][1];
            int max=parent[par][2];
            int reqd=max-min+1;
            if(s==reqd){
                i++;
            }
            else{
                for(int j=i+1;j<=max;j++){
                    if(findParent(i,parent)!=findParent(j,parent)){
                        count++;
                        union(i,j,parent,size);
                    }
                }
                i=max;
            }
        }
        System.out.println(count);
    }
}


//package cf600d2;
import java.io.*;
import java.util.*;
import static java.lang.Math.*;

public class D {
	static int[] dsu;
	public static void main(String[] args) {
		MyScanner sc = new MyScanner();
		int n = sc.nextInt(), m = sc.nextInt();
		dsu = new int[n];
		for(int i = 0; i < n; i++)
			dsu[i] = i;
		for(int i = 0; i < m; i++) {
			int u = dsu(sc.nextInt() - 1), v = dsu(sc.nextInt() - 1);
			dsu[u] = v;
		}
		TreeSet<Integer> seen = new TreeSet<Integer>();
		TreeSet<String> used = new TreeSet<String>();
		int last = -1, ans = 0;
		for(int i = 0; i < n; i++) {
			if(dsu(i) != last && seen.contains(dsu(i)) && used.add(str(dsu(i), last)))
				ans++;
			seen.add(dsu(i));
			last = dsu(i);
		}
		out.println(ans);
		out.close();
	}
	static String str(int a, int b) {
		return min(a, b) + "$" + max(a, b);
	}
	static int dsu(int x) {
		return dsu[x] == x ? x : (dsu[x] = dsu(dsu[x]));
	}
	static PrintWriter out  = new PrintWriter(new BufferedOutputStream(System.out));
	static class MyScanner {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		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;
		}
	}
}


//package cf600d2;
import java.io.*;
import java.util.*;
import static java.lang.Math.*;

public class D {
	static int[] dsu, mx;
	public static void main(String[] args) {
		MyScanner sc = new MyScanner();
		int n = sc.nextInt(), m = sc.nextInt();
		dsu = new int[n];
		mx = new int[n];
		for(int i = 0; i < n; i++)
			dsu[i] = mx[i] = i;
		for(int i = 0; i < m; i++)
			join(sc.nextInt() - 1, sc.nextInt() - 1);
		int ans = 0;
		for(int i = 1; i < n; i++) {
			if(dsu(i) != dsu(i - 1) && mx[dsu(i - 1)] >= i) {
				join(i, i - 1);
				ans++;
			}
		}
		out.println(ans);
		out.close();
	}
	static void join(int u, int v) {
		u = dsu(u);
		v = dsu(v);
		mx[u] = max(mx[u], mx[v]);
		dsu[max(u, v)] = min(u, v);
	}
	static String str(int a, int b) {
		return min(a, b) + "$" + max(a, b);
	}
	static int dsu(int x) {
		return dsu[x] == x ? x : (dsu[x] = dsu(dsu[x]));
	}
	static PrintWriter out  = new PrintWriter(new BufferedOutputStream(System.out));
	static class MyScanner {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		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;
		}
	}
}


//package cf600d2;
import java.io.*;
import java.util.*;
import static java.lang.Math.*;

public class D {
	static int[] dsu, mx;
	public static void main(String[] args) {
		MyScanner sc = new MyScanner();
		int n = sc.nextInt(), m = sc.nextInt();
		dsu = new int[n];
		mx = new int[n];
		for(int i = 0; i < n; i++)
			dsu[i] = mx[i] = i;
		for(int i = 0; i < m; i++)
			join(sc.nextInt() - 1, sc.nextInt() - 1);
		int ans = 0;
		for(int i = 1; i < n; i++) {
			if(dsu(i) == i && mx[dsu(i - 1)] > i) {
				join(i, i - 1);
				ans++;
			}
		}
		out.println(ans);
		out.close();
	}
	static void join(int u, int v) {
		u = dsu(u);
		v = dsu(v);
		mx[min(u, v)] = max(mx[u], mx[v]);
		dsu[max(u, v)] = min(u, v);
	}
	static int dsu(int x) {
		return dsu[x] == x ? x : (dsu[x] = dsu(dsu[x]));
	}
	static PrintWriter out  = new PrintWriter(new BufferedOutputStream(System.out));
	static class MyScanner {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		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.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;

public class Main {
	static class Reader
    {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader()
        {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException
        {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException
        {
            byte[] buf = new byte[(int) (2e6+10)]; // line length
            int cnt = 0, c;
            while ((c = read()) != -1)
            {
                if (c == '\n')
                    break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException
        {
            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;
        }

        public long nextLong() throws IOException
        {
            long 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;
        }

        public double nextDouble() throws IOException
        {
            double ret = 0, div = 1;
            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 (c == '.')
            {
                while ((c = read()) >= '0' && c <= '9')
                {
                    ret += (c - '0') / (div *= 10);
                }
            }

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

        private void fillBuffer() throws IOException
        {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1)
                buffer[0] = -1;
        }

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

        public void close() throws IOException
        {
            if (din == null)
                return;
            din.close();
        }
    }

	public static PrintWriter out = new PrintWriter (new BufferedOutputStream(System.out));
	public static Reader sc = new Reader();

	public static List<Integer>[] edges;

	public static void main(String[] args) throws IOException{

		int n = sc.nextInt();
		int m = sc.nextInt();
		int[] parent = new int[n+1];
		for(int i=0;i<m;++i) {
			int u = sc.nextInt();
			int v = sc.nextInt();
			int up = findRoot(u,parent);
			int vp = findRoot(v,parent);
			if(up != vp)
		     union(up, vp,parent);
		}
		int ans = 0;
		for(int i=0;i<n;++i) {
			int u = findRoot(i,parent);
			int v = findRoot(i+1,parent); // max reach
			if(v < u) {
				union(u,v,parent);
				++ans;
			}
		}
		out.print(ans);
		out.close();
	}

	   public static int findRoot(int curr,int[] parent) {
           if(parent[curr] == 0) return curr;
           return parent[curr] = findRoot(parent[curr],parent);
       }
	   static void union(int u, int v, int[] par){
		   if(u > v) par[v] = u;
		   else par[u] = v;
	    }

}


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

public class D{

    public static int[] par;
    public static int[] sz;
    public static int[] rank;

    public static void main(String[] args) throws IOException{
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(f.readLine());

        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());

        LinkedList<Integer>[] edges = new LinkedList[n+1];

        par = new int[n+1];
        sz = new int[n+1];
        rank = new int[n+1];

        for(int i = 1; i <= n; i++){
            edges[i] = new LinkedList<Integer>();
        }

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

        for(int i = 0; i <= n; i++) {
            par[i] = i;
            sz[i] = 1;
        }

        for(int i = 1; i < n; i++){
            for(int e: edges[i]){
                if(find(i) != find(e)){
                    merge(i, e);
                }
            }
        }

        int[] comps = new int[n+1];
        for(int i = 1; i <= n; i++){
            comps[i] = find(i);
        }

        HashMap<Integer, Integer> begins = new HashMap<Integer, Integer>();
        HashMap<Integer, Integer> ends = new HashMap<Integer, Integer>();

        ArrayList<Integer> newcomps = new ArrayList<Integer>();

        for(int i = 1; i <= n; i++){
            if(!begins.containsKey(comps[i])){
                begins.put(comps[i], i);
                ends.put(comps[i], i);
            }else{
                ends.put(comps[i], i);
            }
        }

        HashSet<Integer> temp = new HashSet<Integer>();

        for(int i = 1; i <= n; i++){
            if(!temp.contains(comps[i])){
                newcomps.add(comps[i]);
                temp.add(comps[i]);
            }if(i == ends.get(comps[i])){
                newcomps.add(comps[i]);
            }
        }

        int sum = 0;

        int total = 0;

        HashSet<Integer> seen = new HashSet<Integer>();

        for(int i: newcomps){
            if(!seen.contains(i)){
                seen.add(i);
                total++;
            }else{
                seen.remove(i);
                if(seen.size() == 0){
                    sum+=total-1;
                    total = 0;
                }
            }

        }

        System.out.println(sum);

    }

    public static int sizeOf(int x) {
        return sz[find(x)];
    }
    public static int find(int x) {
        return par[x] == x ? x : (par[x] = find(par[x]));
    }
    public static void merge(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (rank[fx] < rank[fy]) {
            sz[fy] += sz[fx];
            par[fx] = fy;
        } else if (rank[fy] < rank[fx]) {
            sz[fx] += sz[fy];
            par[fy] = fx;
        } else {
            par[fy] = fx;
            sz[fx] += sz[fy];
            rank[fx]++;
        }
    }
}


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

public class D{

    public static int[] par;
    public static int[] sz;
    public static int[] rank;

    public static void main(String[] args) throws IOException{
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer st = new StringTokenizer(f.readLine());

        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());

        LinkedList<Integer>[] edges = new LinkedList[n+1];

        par = new int[n+1];
        sz = new int[n+1];
        rank = new int[n+1];

        for(int i = 1; i <= n; i++){
            edges[i] = new LinkedList<Integer>();
        }

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

        for(int i = 0; i <= n; i++) {
            par[i] = i;
            sz[i] = 1;
        }

        for(int i = 1; i < n; i++){
            for(int e: edges[i]){
                if(find(i) != find(e)){
                    merge(i, e);
                }
            }
        }

        int[] comps = new int[n+1];
        for(int i = 1; i <= n; i++){
            comps[i] = find(i);
        }

        HashMap<Integer, Integer> begins = new HashMap<Integer, Integer>();
        HashMap<Integer, Integer> ends = new HashMap<Integer, Integer>();

        for(int i = 1; i < n; i++){
            if(!begins.containsKey(comps[i])){
                begins.put(comps[i], i);
                ends.put(comps[i], i);
            }else{
                ends.put(comps[i], i);
            }
        }

        int ctr = 1;

        int sum = 0;

        HashSet<Integer> seen = new HashSet<Integer>();

        while(ctr <= n){
            if(begins.get(comps[ctr]) == ends.get(comps[ctr])){
                ctr++;
                continue;
            }
            seen.add(comps[ctr]);
            int end = ends.get(comps[ctr]);
            ctr++;
            while(ctr < end){
                if(!seen.contains(comps[ctr])){
                    seen.add(comps[ctr]);
                    sum++;
                }
                ctr++;
            }
        }
        System.out.println(sum);

    }

    public static int sizeOf(int x) {
        return sz[find(x)];
    }
    public static int find(int x) {
        return par[x] == x ? x : (par[x] = find(par[x]));
    }
    public static void merge(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (rank[fx] < rank[fy]) {
            sz[fy] += sz[fx];
            par[fx] = fy;
        } else if (rank[fy] < rank[fx]) {
            sz[fx] += sz[fy];
            par[fy] = fx;
        } else {
            par[fy] = fx;
            sz[fx] += sz[fy];
            rank[fx]++;
        }
    }
}


import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Locale;
import java.util.Scanner;

public class DTask {
    private static final String QUICK_ANSWER = "NO";
    private final Scanner in;
    private final StringBuilder out;

    public DTask(Scanner in, StringBuilder out) {
        this.in = in;
        this.out = out;
    }

    public void solve() throws QuickAnswer {
        Graph g = Graph.builder().build(in);
        int[] c = new int[g.n];
        int[] min = new int[g.n + 1];
        int color = 0;
        int[] togo = new int[g.n];
        for (int i = 0; i < g.n; i++) {
            if(c[i] > 0) continue;
            int b = 0;
            int e = 0;
            togo[e++] = i;
            c[i] = ++color;
            min[color] = i;
            while(b < e){
                for(int n : g.neighbors[togo[b++]]){
                    if(c[n] > 0) continue;
                    c[n] = color;
                    togo[e++] = n;
                }
            }
        }

        int minroot = g.n;
        int cnt = 0;
        int[] c2 = new int[g.n];
        for (int i = g.n-1; i >= 0 ; i--) {
            int m = min[c[i]];
            if(c2[m] == 0){
                c2[m] = 1;
                if(m < minroot) minroot = m;
                ++cnt;
            }
            if(i == minroot) --cnt;
        }
        print(cnt);

    }

    // Common functions

    void quickAnswer(String answer) throws QuickAnswer {
        throw new QuickAnswer(answer);
    }

    void quickAnswer() throws QuickAnswer {
        quickAnswer(QUICK_ANSWER);
    }

    static class QuickAnswer extends Exception {
        private String answer;
        public QuickAnswer(String answer) {
            this.answer = answer;
        }
    }

    void print(Object... args) {
        String prefix = "";
        for (Object arg : args) {
            out.append(prefix);
            out.append(arg);
            prefix = " ";
        }
    }

    void println(Object... args) {
        print(args);
        out.append("\n");
    }

    void printsp(Object... args) {
        print(args);
        out.append(" ");
    }

    int nextInt() {
        return in.nextInt();
    }

    long nextLong() {
        return in.nextLong();
    }

    String nextString() {
        String res = in.nextLine();
        return res.trim().isEmpty() ? in.nextLine() : res;
    }

    int[] nextInts(int count) {
        int[] res = new int[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextInt();
        }
        return res;
    }

    int[][] nextInts(int count, int n) {
        int[][] res = new int[n][count];
        for (int i = 0; i < count; ++i) {
            for (int j = 0; j < n; j++) {
                res[j][i] = in.nextInt();
            }
        }
        return res;
    }

    long[] nextLongs(int count) {
        long[] res = new long[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextLong();
        }
        return res;
    }

    long[][] nextLongs(int count, int n) {
        long[][] res = new long[n][count];
        for (int i = 0; i < count; ++i) {
            for (int j = 0; j < n; j++) {
                res[j][i] = in.nextLong();
            }
        }
        return res;
    }

    public static void main(String[] args) {
        doMain(System.in, System.out);
    }

    static void doMain(InputStream inStream, PrintStream outStream) {
        Scanner in = new Scanner(new BufferedInputStream(inStream)).useLocale(Locale.ENGLISH);
        StringBuilder totalOut = new StringBuilder();
        int count = 1;
        //count = in.nextInt();
        while (count-- > 0) {
            try {
                StringBuilder out = new StringBuilder();
                new DTask(in, out).solve();
                totalOut.append(out.toString());
            } catch (QuickAnswer e) {
                totalOut.append(e.answer);
            }
            if (count > 0) {
                totalOut.append("\n");
            }
        }
        outStream.print(totalOut.toString());
    }

    static class Graph {
        final int n;
        final int[][] neighbors;
        final int[] color;
        final int[] edgeFrom;
        final int[] edgeTo;
        final int[] edgeWeight;

        static Graph.Builder builder() {
            return new Graph.Builder();
        }

        static class Builder {
            int adjustIndex = -1;
            boolean withWeights = false;
            int n = -1;
            int m = -1;

            Graph.Builder setAdjustIndex(int adjustIndex) {
                this.adjustIndex = adjustIndex;
                return this;
            }

            Graph.Builder setWithWeights(boolean withWeights) {
                this.withWeights = withWeights;
                return this;
            }

            Graph.Builder setN(int n) {
                this.n = n;
                return this;
            }

            Graph.Builder setM(int m) {
                this.m = m;
                return this;
            }

            Graph build(Scanner in) {
                return new Graph(
                        in,
                        n == -1 ? in.nextInt() : n,
                        m == -1 ? in.nextInt() : m,
                        adjustIndex,
                        withWeights);
            }
        }

        Graph(Scanner in, int n, int m, int adjustIndex, boolean withWeights) {
            this.n = n;
            this.color = new int[n];
            int[] cnt = new int[n];
            edgeFrom = new int[m];
            edgeTo = new int[m];
            edgeWeight = new int[n];
            for (int i = 0; i < m; ++i) {
                int x = in.nextInt() + adjustIndex;
                int y = in.nextInt() + adjustIndex;
                edgeFrom[i] = x;
                edgeTo[i] = y;
                edgeWeight[i] = withWeights ? in.nextInt() : 1;
                cnt[x]++;
                cnt[y]++;
            }
            this.neighbors = new int[n][];
            for (int i = 0; i < n; i++) {
                neighbors[i] = new int[cnt[i]];
            }
            for (int i = 0; i < m; ++i) {
                int from = edgeFrom[i];
                int to = edgeTo[i];
                neighbors[from][--cnt[from]] = to;
                neighbors[to][--cnt[to]] = from;
            }
        }
    }

    static class IntQueue {
        final int[] togo;
        int curr;
        int end;

        public IntQueue(int maxLen) {
            togo = new int[maxLen];
        }

        void add(int val) {
            togo[end++] = val;
        }

        int poll() {
            return togo[curr++];
        }

        boolean isEmpty() {
            return curr == end;
        }
    }

    static class Tree extends Graph {
        final int[] level;
        final int[] parent;
        final int[][] children;

        static Tree.Builder builder() {
            return new Tree.Builder();
        }

        static class Builder extends Graph.Builder {
            private int rootNode = 0;

            Tree.Builder setRootNode(int rootNode) {
                this.rootNode = rootNode;
                return this;
            }

            public Tree build(Scanner in) {
                return new Tree(
                        in,
                        n == -1 ? in.nextInt() : n,
                        adjustIndex,
                        withWeights,
                        rootNode);
            }
        }

        Tree(Scanner in, int n, int adjustIndex, boolean withWeights, int rootNode) {
            super(in, n, n - 1, adjustIndex, withWeights);
            level = new int[n];
            parent = new int[n];
            children = new int[n][];

            IntQueue iq = new IntQueue(n);
            level[rootNode] = 0;
            parent[rootNode] = -1;
            iq.add(rootNode);
            while (!iq.isEmpty()) {
                int node = iq.poll();
                int childLevel = level[node] + 1;
                if (parent[node] == -1) {
                    children[node] = new int[neighbors[node].length];
                } else {
                    children[node] = new int[neighbors[node].length - 1];
                }
                int curr = 0;
                for (int neighbor : neighbors[node]) {
                    if (neighbor == parent[node]) continue;
                    level[neighbor] = childLevel;
                    parent[neighbor] = node;
                    children[node][curr++] = neighbor;
                    iq.add(neighbor);
                }
            }
        }
    }
}


import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Locale;
import java.util.Scanner;

public class DTask {
    private static final String QUICK_ANSWER = "NO";
    private final Scanner in;
    private final StringBuilder out;

    public DTask(Scanner in, StringBuilder out) {
        this.in = in;
        this.out = out;
    }

    public void solve() throws QuickAnswer {
        Graph g = Graph.builder().build(in);
        int[] c = new int[g.n];
        int[] min = new int[g.n + 1];
        int color = 0;
        int[] togo = new int[g.n];
        for (int i = 0; i < g.n; i++) {
            if(c[i] > 0) continue;
            int b = 0;
            int e = 0;
            togo[e++] = i;
            c[i] = ++color;
            min[color] = i;
            while(b < e){
                for(int n : g.neighbors[togo[b++]]){
                    if(c[n] > 0) continue;
                    c[n] = color;
                    togo[e++] = n;
                }
            }
        }

        int minroot = g.n;
        int cnt = 0;
        int[] c2 = new int[g.n];
        for (int i = g.n-1; i >= 0 ; i--) {
            int m = min[c[i]];
            if(c2[m] == 0){
                c2[m] = 1;
                if(m < minroot) minroot = m;
                ++cnt;
            }
            if(i == minroot) --cnt;
        }
        print(cnt);

    }

    // Common functions

    void quickAnswer(String answer) throws QuickAnswer {
        throw new QuickAnswer(answer);
    }

    void quickAnswer() throws QuickAnswer {
        quickAnswer(QUICK_ANSWER);
    }

    static class QuickAnswer extends Exception {
        private String answer;
        public QuickAnswer(String answer) {
            this.answer = answer;
        }
    }

    void print(Object... args) {
        String prefix = "";
        for (Object arg : args) {
            out.append(prefix);
            out.append(arg);
            prefix = " ";
        }
    }

    void println(Object... args) {
        print(args);
        out.append("\n");
    }

    void printsp(Object... args) {
        print(args);
        out.append(" ");
    }

    int nextInt() {
        return in.nextInt();
    }

    long nextLong() {
        return in.nextLong();
    }

    String nextString() {
        String res = in.nextLine();
        return res.trim().isEmpty() ? in.nextLine() : res;
    }

    int[] nextInts(int count) {
        int[] res = new int[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextInt();
        }
        return res;
    }

    int[][] nextInts(int count, int n) {
        int[][] res = new int[n][count];
        for (int i = 0; i < count; ++i) {
            for (int j = 0; j < n; j++) {
                res[j][i] = in.nextInt();
            }
        }
        return res;
    }

    long[] nextLongs(int count) {
        long[] res = new long[count];
        for (int i = 0; i < count; ++i) {
            res[i] = in.nextLong();
        }
        return res;
    }

    long[][] nextLongs(int count, int n) {
        long[][] res = new long[n][count];
        for (int i = 0; i < count; ++i) {
            for (int j = 0; j < n; j++) {
                res[j][i] = in.nextLong();
            }
        }
        return res;
    }

    public static void main(String[] args) {
        doMain(System.in, System.out);
    }

    static void doMain(InputStream inStream, PrintStream outStream) {
        Scanner in = new Scanner(new BufferedInputStream(inStream)).useLocale(Locale.ENGLISH);
        StringBuilder totalOut = new StringBuilder();
        int count = 1;
        //count = in.nextInt();
        while (count-- > 0) {
            try {
                StringBuilder out = new StringBuilder();
                new DTask(in, out).solve();
                totalOut.append(out.toString());
            } catch (QuickAnswer e) {
                totalOut.append(e.answer);
            }
            if (count > 0) {
                totalOut.append("\n");
            }
        }
        outStream.print(totalOut.toString());
    }

    static class Graph {
        final int n;
        final int[][] neighbors;
        final int[] color;
        final int[] edgeFrom;
        final int[] edgeTo;
        final int[] edgeWeight;

        static Graph.Builder builder() {
            return new Graph.Builder();
        }

        static class Builder {
            int adjustIndex = -1;
            boolean withWeights = false;
            int n = -1;
            int m = -1;

            Graph.Builder setAdjustIndex(int adjustIndex) {
                this.adjustIndex = adjustIndex;
                return this;
            }

            Graph.Builder setWithWeights(boolean withWeights) {
                this.withWeights = withWeights;
                return this;
            }

            Graph.Builder setN(int n) {
                this.n = n;
                return this;
            }

            Graph.Builder setM(int m) {
                this.m = m;
                return this;
            }

            Graph build(Scanner in) {
                return new Graph(
                        in,
                        n == -1 ? in.nextInt() : n,
                        m == -1 ? in.nextInt() : m,
                        adjustIndex,
                        withWeights);
            }
        }

        Graph(Scanner in, int n, int m, int adjustIndex, boolean withWeights) {
            this.n = n;
            this.color = new int[n];
            int[] cnt = new int[n];
            edgeFrom = new int[m];
            edgeTo = new int[m];
            edgeWeight = new int[m];
            for (int i = 0; i < m; ++i) {
                int x = in.nextInt() + adjustIndex;
                int y = in.nextInt() + adjustIndex;
                edgeFrom[i] = x;
                edgeTo[i] = y;
                edgeWeight[i] = withWeights ? in.nextInt() : 1;
                cnt[x]++;
                cnt[y]++;
            }
            this.neighbors = new int[n][];
            for (int i = 0; i < n; i++) {
                neighbors[i] = new int[cnt[i]];
            }
            for (int i = 0; i < m; ++i) {
                int from = edgeFrom[i];
                int to = edgeTo[i];
                neighbors[from][--cnt[from]] = to;
                neighbors[to][--cnt[to]] = from;
            }
        }
    }

    static class IntQueue {
        final int[] togo;
        int curr;
        int end;

        public IntQueue(int maxLen) {
            togo = new int[maxLen];
        }

        void add(int val) {
            togo[end++] = val;
        }

        int poll() {
            return togo[curr++];
        }

        boolean isEmpty() {
            return curr == end;
        }
    }

    static class Tree extends Graph {
        final int[] level;
        final int[] parent;
        final int[][] children;

        static Tree.Builder builder() {
            return new Tree.Builder();
        }

        static class Builder extends Graph.Builder {
            private int rootNode = 0;

            Tree.Builder setRootNode(int rootNode) {
                this.rootNode = rootNode;
                return this;
            }

            public Tree build(Scanner in) {
                return new Tree(
                        in,
                        n == -1 ? in.nextInt() : n,
                        adjustIndex,
                        withWeights,
                        rootNode);
            }
        }

        Tree(Scanner in, int n, int adjustIndex, boolean withWeights, int rootNode) {
            super(in, n, n - 1, adjustIndex, withWeights);
            level = new int[n];
            parent = new int[n];
            children = new int[n][];

            IntQueue iq = new IntQueue(n);
            level[rootNode] = 0;
            parent[rootNode] = -1;
            iq.add(rootNode);
            while (!iq.isEmpty()) {
                int node = iq.poll();
                int childLevel = level[node] + 1;
                if (parent[node] == -1) {
                    children[node] = new int[neighbors[node].length];
                } else {
                    children[node] = new int[neighbors[node].length - 1];
                }
                int curr = 0;
                for (int neighbor : neighbors[node]) {
                    if (neighbor == parent[node]) continue;
                    level[neighbor] = childLevel;
                    parent[neighbor] = node;
                    children[node][curr++] = neighbor;
                    iq.add(neighbor);
                }
            }
        }
    }
}


import java.util.*;
import java.io.*;
public class MyClass {
    static long gcd(long a, long b){
        if(b==0)
            return a;
        else
            return gcd(b,a%b);
    }
    public static void main(String args[]) {
      FastReader sc = new FastReader();
      PrintWriter pw = new PrintWriter(System.out);
      int n = sc.nextInt();
      int m = sc.nextInt();
      Graph g = new Graph(n);
      while(m-->0){
          int x = sc.nextInt();
          int y = sc.nextInt();
          g.addEdge(x,y);
      }
      int ans=0;
      for(int i=1;i<=n;i++){
          if(g.visited[i]==0){
              if(g.maxind>i){
                  ans++;
              }
              g.dfs(i);
          }
      }
      pw.println(ans);

      pw.flush();
      pw.close();
    }
}
class FastReader
	{
		BufferedReader br;
		StringTokenizer st;

		public FastReader()
		{
			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;
		}
	}
class Graph{
        int vertices;
        LinkedList<Integer> adj[];
        int visited[];
        int maxind;
        Graph(int v){
            vertices = v;
            adj = new LinkedList[vertices+1];
            visited = new int[vertices+1];
            maxind=0;
            for(int i=1;i<=vertices;i++){
                adj[i] = new LinkedList();
            }
        }
        public void addEdge(int x,int y){
            adj[x].add(y);
            adj[y].add(x);
        }
        public void dfs(int source){
            maxind = Math.max(maxind,source);
            visited[source]=1;
            for(Integer num : adj[source]){
                if(visited[num]==0){
                    visited[num]=1;
                    dfs(num);
                }
            }
        }

}


import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TreeSet;

public final class CF_600_D2_D
{

	static boolean verb=true;
	static void log(Object X){if (verb) System.err.println(X);}
	static void log(Object[] X){if (verb) {for (Object U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X){if (verb) {for (int U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X,int L){if (verb) {for (int i=0;i<L;i++) System.err.print(X[i]+" ");System.err.println("");}}
	static void log(long[] X){if (verb) {for (long U:X) System.err.print(U+" ");System.err.println("");}}

	static void logWln(Object X){if (verb) System.err.print(X);}
	static void info(Object o){	System.out.println(o);}
	static void output(Object o){outputWln(""+o+"\n");	}
	static void outputWln(Object o){try {out.write(""+ o);} catch (Exception e) {}}

	static long mod=1000000007;

	// Global vars
	static BufferedWriter out;
	static InputReader reader;

	static class Composite implements Comparable<Composite>{
		int idx;
		int v;

		public int compareTo(Composite X) {
			if (v!=X.v)
				return v-X.v;
			return idx-X.idx;

		}

		public Composite(int idx, int v) {
			this.idx = idx;
			this.v = v;
		}

	}

	static void test() {
		log("testing");

		log("done");

	}

	static int[] id,sz,mx,mn;

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

	static void qunion(int p, int q) {
		int i = root(p);
		int j = root(q);
		if (i == j) return;
		if (sz[i] < sz[j]) { id[i] = j; sz[j] += sz[i]; mx[j]=Math.max(mx[i],mx[j]);mn[j]=Math.min(mn[i],mn[j]);}
		else { id[j] = i; sz[i] += sz[j]; mx[i]=Math.max(mx[i],mx[j]);mn[i]=Math.min(mn[i],mn[j]); }
	}

	static void process() throws Exception {

		//arrayTest();

		out = new BufferedWriter(new OutputStreamWriter(System.out));
		reader = new InputReader(System.in);

		int n=reader.readInt();
		int m=reader.readInt();

		sz=new int[n];
		id=new int[n];
		mx=new int[n];
		mn=new int[n];

		for (int i=0;i<n;i++) {
			id[i]=i;
			mx[i]=i;
			mn[i]=i;
			sz[i]=1;
		}

		for (int i=0;i<m;i++) {
			int u=reader.readInt()-1;
			int v=reader.readInt()-1;
			qunion(u,v);
		}

		boolean[] visited=new boolean[n];
		int res=0;
		for (int u=0;u<n;u++) {
			int r=root(u);
			if (!visited[r]) {
				visited[r]=true;
				int a=mn[r];
				int b=mx[r];
				int s=sz[r];
				//log("r:"+r+" a:"+a+" b:"+b+" s:"+s);
				if (s<b-a+1) {
					//log("need to do something");
					int i=a;
					while (i<=b) {
						if (root(i)!=r) {
							res++;
							qunion(i,r);
							r=root(r);
							visited[r]=true;
							b=mx[r];
						}
						i++;
					}
				}
			}
		}
		output(res);

		try {
			out.close();
		} catch (Exception e) {
		}

	}

	public static void main(String[] args) throws Exception {
		process();

	}

	static final class InputReader {
		private final InputStream stream;
		private final byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		private int read() throws IOException {
			if (curChar >= numChars) {
				curChar = 0;
				numChars = stream.read(buf);
				if (numChars <= 0) {
					return -1;
				}
			}
			return buf[curChar++];
		}

		public final String readString() throws IOException {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res = new StringBuilder();
			do {
				res.append((char) c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public final int readInt() throws IOException {
			int c = read();
			boolean neg = false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d = (char) c;
			// log("d:"+d);
			if (d == '-') {
				neg = true;
				c = read();
			}
			int res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			// log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		public final long readLong() throws IOException {
			int c = read();
			boolean neg = false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d = (char) c;
			// log("d:"+d);
			if (d == '-') {
				neg = true;
				c = read();
			}
			long res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			// log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		private boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}
	}

}


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

public class Main {
    static int inf = (int) 1e9 + 7;
    static int n, m;
    static dsu a;
    static int b[];
    static int c[];

    public static void main(String[] args) throws IOException {
        sc = new Scanner(System.in);
        pw = new PrintWriter(System.out);
        n = sc.nextInt();
        m = sc.nextInt();
        a = new dsu(n);
        b = new int [n];
        c = new int [n];
        for(int i = 0;i < m;i++) {
            int v1 = sc.nextInt() - 1;
            int v2 = sc.nextInt() - 1;
            a.union(v1, v2);
        }
        for(int i = 0;i < n;i++) {
            c[i] = a.get(i);
            b[a.get(i)] = i;
        }
        int ans = 0;
        int r = -1;
        int num = 0;
        for(int i = 0;i < n;i++) {
            if (i > r) {
                r = b[c[i]];
                num = a.get(c[i]);
            }else{
                if (num != a.get(c[i])) ans++;

                if (b[c[i]] > r) {
                    r = b[c[i]];
                    a.union(num, a.get(c[i]));
                    num = a.get(c[i]);
                }

            }
        }
        pw.println(ans);
        pw.close();
    }

    static Scanner sc;
    static PrintWriter pw;

    static class Scanner {
        BufferedReader br;
        StringTokenizer st = new StringTokenizer("");

        Scanner(InputStream in) throws FileNotFoundException {
            br = new BufferedReader(new InputStreamReader(in));
        }

        Scanner(String in) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(in));
        }

        String next() throws IOException {
            while (!st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

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

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

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

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

    int get(int v) {
        if (v == parent[v]) return v;
        return parent[v] = get(parent[v]);
    }

    void union(int v1, int v2) {
        parent[get(v1)] = get(v2);
    }
}


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

public class Main {
    static int inf = (int) 1e9 + 7;
    static int n, m;
    static dsu a;
    static int b[];
    static int c[];

    public static void main(String[] args) throws IOException {
        sc = new Scanner(System.in);
        pw = new PrintWriter(System.out);
        n = sc.nextInt();
        m = sc.nextInt();
        a = new dsu(n);
        b = new int [n];
        c = new int [n];
        for(int i = 0;i < m;i++) {
            int v1 = sc.nextInt() - 1;
            int v2 = sc.nextInt() - 1;
            a.union(v1, v2);
        }
        for(int i = 0;i < n;i++) {
            c[i] = a.get(i);
            b[a.get(i)] = i;
        }
        int ans = 0;
        int r = -1;
        int num = 0;
        for(int i = 0;i < n;i++) {
            if (i > r) {
                r = b[c[i]];
                num = c[i];
            }else{

                if (b[c[i]] > r) {
                    r = b[c[i]];
                    if (num != a.get(c[i])) ans++;

                    a.union(num, c[i]);
                    num = a.get(c[i]);
                }else{
                    if (num != a.get(c[i])) {
                        ans++;
                        a.union(c[i], num);
                    }
                }

            }
        }
        pw.println(ans);
        pw.close();
    }

    static Scanner sc;
    static PrintWriter pw;

    static class Scanner {
        BufferedReader br;
        StringTokenizer st = new StringTokenizer("");

        Scanner(InputStream in) throws FileNotFoundException {
            br = new BufferedReader(new InputStreamReader(in));
        }

        Scanner(String in) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(in));
        }

        String next() throws IOException {
            while (!st.hasMoreTokens()) st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

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

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

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

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

    int get(int v) {
        if (v == parent[v]) return v;
        return parent[v] = get(parent[v]);
    }

    void union(int v1, int v2) {
        parent[get(v1)] = get(v2);
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();

            TaskD.Node[] nodes = new TaskD.Node[n];
            for (int i = 0; i < n; i++) {
                nodes[i] = new TaskD.Node();
                nodes[i].l = nodes[i].r = i;
            }

            int[][] edges = new int[m][2];
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < 2; j++) {
                    edges[i][j] = in.readInt() - 1;
                }
            }

            for (int[] e : edges) {
                TaskD.Node.merge(nodes[e[0]], nodes[e[1]]);
            }

            int cc = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    cc++;
                }
            }

            for (int i = 0; i < n; i++) {
                nodes[i].init();
            }

            for (int[] e : edges) {
                TaskD.Node a = nodes[e[0]].find();
                TaskD.Node b = nodes[e[1]].find();
                if (a.r > b.l) {
                    TaskD.Node tmp = a;
                    a = b;
                    b = tmp;
                }

                while (a.find().r < b.find().l) {
                    TaskD.Node next = nodes[a.find().r + 1].find();
                    TaskD.Node.merge(a, next);
                    a.find().r = next.r;
                }
            }

            int curCC = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    curCC++;
                }
            }

            out.println(cc - curCC);
        }

        static class Node {
            TaskD.Node p = this;
            int rank;
            int l;
            int r;

            public void init() {
                p = this;
                rank = 0;
            }

            public TaskD.Node find() {
                return p.p == p ? p : (p = p.find());
            }

            public static void merge(TaskD.Node a, TaskD.Node b) {
                a = a.find();
                b = b.find();
                if (a == b) {
                    return;
                }
                if (a.rank == b.rank) {
                    a.rank++;
                }
                if (a.rank > b.rank) {
                    b.p = a;
                } else {
                    a.p = b;
                }
            }

        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();

            TaskD.Node[] nodes = new TaskD.Node[n];
            for (int i = 0; i < n; i++) {
                nodes[i] = new TaskD.Node();
                nodes[i].l = nodes[i].r = i;
            }

            int[][] edges = new int[m][2];
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < 2; j++) {
                    edges[i][j] = in.readInt() - 1;
                }
            }

            for (int[] e : edges) {
                TaskD.Node.merge(nodes[e[0]], nodes[e[1]]);
            }

            int cc = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    cc++;
                }
            }

            for (int i = 0; i < n; i++) {
                nodes[i].init();
            }

            for (int[] e : edges) {
                TaskD.Node a = nodes[e[0]].find();
                TaskD.Node b = nodes[e[1]].find();
                if (a.r > b.l) {
                    TaskD.Node tmp = a;
                    a = b;
                    b = tmp;
                }

                while (a.r < b.l) {
                    TaskD.Node next = nodes[a.r + 1].find();
                    a.r = next.r;
                    TaskD.Node.merge(a, next);
                }
            }

            int curCC = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    curCC++;
                }
            }

            out.println(cc - curCC);
        }

        static class Node {
            TaskD.Node p = this;
            int rank;
            int l;
            int r;

            public void init() {
                p = this;
                rank = 0;
            }

            public TaskD.Node find() {
                return p.p == p ? p : (p = p.find());
            }

            public static void merge(TaskD.Node a, TaskD.Node b) {
                a = a.find();
                b = b.find();
                if (a == b) {
                    return;
                }
                if (a.rank == b.rank) {
                    a.rank++;
                }
                if (a.rank > b.rank) {
                    b.p = a;
                } else {
                    a.p = b;
                }
            }

        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();

            TaskD.Node[] nodes = new TaskD.Node[n];
            for (int i = 0; i < n; i++) {
                nodes[i] = new TaskD.Node();
                nodes[i].l = nodes[i].r = i;
            }

            int[][] edges = new int[m][2];
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < 2; j++) {
                    edges[i][j] = in.readInt() - 1;
                }
            }

            for (int[] e : edges) {
                TaskD.Node.merge(nodes[e[0]], nodes[e[1]]);
            }

            int cc = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    cc++;
                }
            }

            for (int i = 0; i < n; i++) {
                nodes[i].init();
            }

            for (int[] e : edges) {
                TaskD.Node a = nodes[e[0]].find();
                TaskD.Node b = nodes[e[1]].find();
                if (a.r > b.l) {
                    TaskD.Node tmp = a;
                    a = b;
                    b = tmp;
                }

                while (a.find().r < b.find().l) {
                    TaskD.Node next = nodes[a.r + 1].find();
                    TaskD.Node.merge(a, next);
                    a.find().r = next.r;
                }
            }

            int curCC = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    curCC++;
                }
            }

            out.println(cc - curCC);
        }

        static class Node {
            TaskD.Node p = this;
            int rank;
            int l;
            int r;

            public void init() {
                p = this;
                rank = 0;
            }

            public TaskD.Node find() {
                return p.p == p ? p : (p = p.find());
            }

            public static void merge(TaskD.Node a, TaskD.Node b) {
                a = a.find();
                b = b.find();
                if (a == b) {
                    return;
                }
                if (a.rank == b.rank) {
                    a.rank++;
                }
                if (a.rank > b.rank) {
                    b.p = a;
                } else {
                    a.p = b;
                }
            }

        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();

            TaskD.Node[] nodes = new TaskD.Node[n];
            for (int i = 0; i < n; i++) {
                nodes[i] = new TaskD.Node();
                nodes[i].l = nodes[i].r = i;
            }

            int[][] edges = new int[m][2];
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < 2; j++) {
                    edges[i][j] = in.readInt();
                }
            }

            for (int[] e : edges) {
                TaskD.Node.merge(nodes[e[0]], nodes[e[1]]);
            }

            int cc = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    cc++;
                }
            }

            for (int i = 0; i < n; i++) {
                nodes[i].init();
            }

            for (int[] e : edges) {
                TaskD.Node a = nodes[e[0]].find();
                TaskD.Node b = nodes[e[1]].find();
                if (a.l > b.l) {
                    TaskD.Node tmp = a;
                    a = b;
                    b = tmp;
                }

                while (a.r < b.l) {
                    TaskD.Node next = nodes[a.r + 1].find();
                    a.r = next.r;
                    TaskD.Node.merge(a, next);
                }
            }

            int curCC = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    curCC++;
                }
            }

            out.println(cc - curCC);
        }

        static class Node {
            TaskD.Node p = this;
            int rank;
            int l;
            int r;

            public void init() {
                p = this;
                rank = 0;
            }

            public TaskD.Node find() {
                return p.p == p ? p : (p = p.find());
            }

            public static void merge(TaskD.Node a, TaskD.Node b) {
                a = a.find();
                b = b.find();
                if (a == b) {
                    return;
                }
                if (a.rank == b.rank) {
                    a.rank++;
                }
                if (a.rank > b.rank) {
                    b.p = a;
                } else {
                    a.p = b;
                }
            }

        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();

            TaskD.Node[] nodes = new TaskD.Node[n];
            for (int i = 0; i < n; i++) {
                nodes[i] = new TaskD.Node();
                nodes[i].l = nodes[i].r = i;
            }

            int[][] edges = new int[m][2];
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < 2; j++) {
                    edges[i][j] = in.readInt() - 1;
                }
            }

            for (int[] e : edges) {
                TaskD.Node.merge(nodes[e[0]], nodes[e[1]]);
            }

            int cc = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    cc++;
                }
            }

            for (int i = 0; i < n; i++) {
                nodes[i].init();
            }

            for (int[] e : edges) {
                TaskD.Node a = nodes[e[0]].find();
                TaskD.Node b = nodes[e[1]].find();
                if (a.r > b.l) {
                    TaskD.Node tmp = a;
                    a = b;
                    b = tmp;
                }

                while (a.find().r < b.find().l) {
                    TaskD.Node next = nodes[a.r + 1].find();
                    a.find().r = next.r;
                    TaskD.Node.merge(a, next);
                }
            }

            int curCC = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    curCC++;
                }
            }

            out.println(cc - curCC);
        }

        static class Node {
            TaskD.Node p = this;
            int rank;
            int l;
            int r;

            public void init() {
                p = this;
                rank = 0;
            }

            public TaskD.Node find() {
                return p.p == p ? p : (p = p.find());
            }

            public static void merge(TaskD.Node a, TaskD.Node b) {
                a = a.find();
                b = b.find();
                if (a == b) {
                    return;
                }
                if (a.rank == b.rank) {
                    a.rank++;
                }
                if (a.rank > b.rank) {
                    b.p = a;
                } else {
                    a.p = b;
                }
            }

        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.io.Closeable;
import java.io.Writer;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws Exception {
        Thread thread = new Thread(null, new TaskAdapter(), "", 1 << 27);
        thread.start();
        thread.join();
    }

    static class TaskAdapter implements Runnable {
        @Override
        public void run() {
            InputStream inputStream = System.in;
            OutputStream outputStream = System.out;
            FastInput in = new FastInput(inputStream);
            FastOutput out = new FastOutput(outputStream);
            TaskD solver = new TaskD();
            solver.solve(1, in, out);
            out.close();
        }
    }

    static class TaskD {
        public void solve(int testNumber, FastInput in, FastOutput out) {
            int n = in.readInt();
            int m = in.readInt();

            TaskD.Node[] nodes = new TaskD.Node[n];
            for (int i = 0; i < n; i++) {
                nodes[i] = new TaskD.Node();
                nodes[i].l = nodes[i].r = i;
            }

            int[][] edges = new int[m][2];
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < 2; j++) {
                    edges[i][j] = in.readInt() - 1;
                }
            }

            for (int[] e : edges) {
                TaskD.Node.merge(nodes[e[0]], nodes[e[1]]);
            }

            int cc = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    cc++;
                }
            }

            for (int i = 0; i < n; i++) {
                nodes[i].init();
            }

            for (int[] e : edges) {
                TaskD.Node a = nodes[e[0]].find();
                TaskD.Node b = nodes[e[1]].find();
                if (a.r > b.l) {
                    TaskD.Node tmp = a;
                    a = b;
                    b = tmp;
                }

                while (a.find().r < b.find().l) {
                    TaskD.Node next = nodes[a.r + 1].find();
                    a.r = next.r;
                    TaskD.Node.merge(a, next);
                }
            }

            int curCC = 0;
            for (int i = 0; i < n; i++) {
                if (nodes[i].find() == nodes[i]) {
                    curCC++;
                }
            }

            out.println(cc - curCC);
        }

        static class Node {
            TaskD.Node p = this;
            int rank;
            int l;
            int r;

            public void init() {
                p = this;
                rank = 0;
            }

            public TaskD.Node find() {
                return p.p == p ? p : (p = p.find());
            }

            public static void merge(TaskD.Node a, TaskD.Node b) {
                a = a.find();
                b = b.find();
                if (a == b) {
                    return;
                }
                if (a.rank == b.rank) {
                    a.rank++;
                }
                if (a.rank > b.rank) {
                    b.p = a;
                } else {
                    a.p = b;
                }
            }

        }

    }

    static class FastOutput implements AutoCloseable, Closeable {
        private StringBuilder cache = new StringBuilder(10 << 20);
        private final Writer os;

        public FastOutput(Writer os) {
            this.os = os;
        }

        public FastOutput(OutputStream os) {
            this(new OutputStreamWriter(os));
        }

        public FastOutput println(int c) {
            cache.append(c).append('\n');
            return this;
        }

        public FastOutput flush() {
            try {
                os.append(cache);
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
            return this;
        }

        public void close() {
            flush();
            try {
                os.close();
            } catch (IOException e) {
                throw new UncheckedIOException(e);
            }
        }

        public String toString() {
            return cache.toString();
        }

    }

    static class FastInput {
        private final InputStream is;
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastInput(InputStream is) {
            this.is = is;
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    bufLen = -1;
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

    }
}


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 + 1);
        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;
        }
    }
}