import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.*;
import java.io.*;
public class codeforces
{
   static class Student{
       int x,y;
        Student(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
    /*static int prime[];
    static void sieveOfEratosthenes(int n)
    {
        // Create a boolean array "prime[0..n]" and initialize
        // all entries it as true. A value in prime[i] will
        // finally be false if i is Not a prime, else true.
        int pos=0;
        prime= new int[n+1];
        for(int p = 2; p*p <=n; p++)
        {
            // If prime[p] is not changed, then it is a prime
            if(prime[p] == 0)
            {
                // Update all multiples of p
                prime[p]=p;
                for(int i = p*p; i <= n; i += p)
                    prime[i] = p;
            }
        }
    }*/
static    class Sortbyroll implements Comparator<Student>
{
    // Used for sorting in ascending order of
    // roll number
    public int compare(Student c, Student b)
    {
        return c.x-b.x;
    }
}
    static 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;
        }
    }
    static class Edge{
        int a,b;
        Edge(int a,int b){
            this.a=a;
            this.b=b;
        }
    }
    static int parent[];
    static int rank[];
    public static void main(String[] args){
        //long sum=0;
        FastReader sc=new FastReader();
        int n,m,min,max,ans=0,x,y,i,j;
        n=sc.nextInt();
        m=sc.nextInt();
        HashMap<Integer,Integer>map=new HashMap<>();
        ArrayList<ArrayList<Integer>>adj=new ArrayList<>();
        for(i=0;i<=n;i++)
            adj.add(new ArrayList<>());
        for(i=0;i<m;i++){
            x=sc.nextInt();
            y=sc.nextInt();
            adj.get(x).add(y);
            adj.get(y).add(x);
            map.put(x,1);
            map.put(y,1);
        }
        int bo[]=new int[n+1];
        ArrayList<Student>arr=new ArrayList<>();
        for(i=1;i<=n;i++){
            if(bo[i]==0&&map.containsKey(i)){
                Queue<Integer>q=new LinkedList<>();
                min=Integer.MAX_VALUE;
                max=Integer.MIN_VALUE;
                q.add(i);
                bo[i]=1;
                while(!q.isEmpty()){
                    min=Math.min(min,q.peek());
                    max=Math.max(max,q.peek());
                    for(j=0;j<adj.get(q.peek()).size();j++){
                        if(bo[adj.get(q.peek()).get(j)]==0){
                            q.add(adj.get(q.peek()).get(j));
                            bo[adj.get(q.peek()).get(j)]=1;
                        }
                    }
                    q.poll();
                }
                arr.add(new Student(min,max));
            }
        }
        Collections.sort(arr,new Sortbyroll());
        Stack<Student>s=new Stack<>();
        s.push(arr.get(0));
        Student temp;
        for(i=1;i<arr.size();i++){
            if(s.peek().y>arr.get(i).x){
                temp=s.pop();
                s.push(new Student(temp.x,Math.max(temp.y,arr.get(i).y)));
                ++ans;
            }
            else{
                s.push(new Student(arr.get(i).x,arr.get(i).y));
            }
        }
        while(!s.isEmpty()){
            for(i=s.peek().x;i<=s.peek().y;i++){
                if(!map.containsKey(i))
                    ++ans;
            }
            //System.out.println(s.peek().x+" "+s.peek().y);
            s.pop();
        }
        System.out.println(ans);
    }
 /*static long power(long x, long y, long p)
{
    long res = 1;      // Initialize result

    x = x % p;  // Update x if it is more than or
                // equal to p

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if ((y & (long)1)%2!=0)
            res = (res*x) % p;

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x) % p;
    }
    return res%p;
} */
   static int find(int x)
    {
        // Finds the representative of the set
        // that x is an element of
        while(parent[x]!=x)
        {
            // if x is not the parent of itself
            // Then x is not the representative of
            // his set,
            x=parent[x];

            // so we recursively call Find on its parent
            // and move i's node directly under the
            // representative of this set
        }

        return x;
    }
    static void union(int x, int y)
    {
        // Find representatives of two sets
        int xRoot = find(x), yRoot = find(y);

        // Elements are in the same set, no need
        // to unite anything.
        if (xRoot == yRoot)
            return;

         // If x's rank is less than y's rank
        if (rank[xRoot] < rank[yRoot])

            // Then move x under y  so that depth
            // of tree remains less
            parent[xRoot] = yRoot;

        // Else if y's rank is less than x's rank
        else if (rank[yRoot] < rank[xRoot])

            // Then move y under x so that depth of
            // tree remains less
            parent[yRoot] = xRoot;

        else // if ranks are the same
        {
            // Then move y under x (doesn't matter
            // which one goes where)
            parent[yRoot] = xRoot;

            // And increment the the result tree's
            // rank by 1
            rank[xRoot] = rank[xRoot] + 1;
        }
    }
    static long gcd(long a, long b)
    {
        if (a == 0)
            return b;
        return gcd(b % a, a);
    }
}


import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.*;
import java.io.*;
public class codeforces
{
   static class Student{
       int x,y;
        Student(int x,int y){
            this.x=x;
            this.y=y;
        }
    }
    /*static int prime[];
    static void sieveOfEratosthenes(int n)
    {
        // Create a boolean array "prime[0..n]" and initialize
        // all entries it as true. A value in prime[i] will
        // finally be false if i is Not a prime, else true.
        int pos=0;
        prime= new int[n+1];
        for(int p = 2; p*p <=n; p++)
        {
            // If prime[p] is not changed, then it is a prime
            if(prime[p] == 0)
            {
                // Update all multiples of p
                prime[p]=p;
                for(int i = p*p; i <= n; i += p)
                    prime[i] = p;
            }
        }
    }*/
static    class Sortbyroll implements Comparator<Student>
{
    // Used for sorting in ascending order of
    // roll number
    public int compare(Student c, Student b)
    {
        return c.x-b.x;
    }
}
    static 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;
        }
    }
    static class Edge{
        int a,b;
        Edge(int a,int b){
            this.a=a;
            this.b=b;
        }
    }
    static int parent[];
    static int rank[];
    public static void main(String[] args){
        //long sum=0;
        FastReader sc=new FastReader();
        int n,m,min,max,ans=0,x,y,i,j;
        n=sc.nextInt();
        m=sc.nextInt();
        HashMap<Integer,Integer>map=new HashMap<>();
        ArrayList<ArrayList<Integer>>adj=new ArrayList<>();
        for(i=0;i<=n;i++)
            adj.add(new ArrayList<>());
        for(i=0;i<m;i++){
            x=sc.nextInt();
            y=sc.nextInt();
            adj.get(x).add(y);
            adj.get(y).add(x);
            map.put(x,1);
            map.put(y,1);
        }
        int bo[]=new int[n+1];
        ArrayList<Student>arr=new ArrayList<>();
        for(i=1;i<=n;i++){
            if(bo[i]==0&&map.containsKey(i)){
                Queue<Integer>q=new LinkedList<>();
                min=Integer.MAX_VALUE;
                max=Integer.MIN_VALUE;
                q.add(i);
                bo[i]=1;
                while(!q.isEmpty()){
                    min=Math.min(min,q.peek());
                    max=Math.max(max,q.peek());
                    for(j=0;j<adj.get(q.peek()).size();j++){
                        if(bo[adj.get(q.peek()).get(j)]==0){
                            q.add(adj.get(q.peek()).get(j));
                            bo[adj.get(q.peek()).get(j)]=1;
                        }
                    }
                    q.poll();
                }
                arr.add(new Student(min,max));
            }
        }
        Collections.sort(arr,new Sortbyroll());
        Stack<Student>s=new Stack<>();
        s.push(arr.get(0));
        Student temp;
        for(i=1;i<arr.size();i++){
            if(s.peek().y>arr.get(i).x){
                temp=s.pop();
                s.push(new Student(temp.x,arr.get(i).y));
                ++ans;
            }
            else{
                s.push(new Student(arr.get(i).x,arr.get(i).y));
            }
        }
        while(!s.isEmpty()){
            for(i=s.peek().x;i<=s.peek().y;i++){
                if(!map.containsKey(i))
                    ++ans;
            }
            //System.out.println(s.peek().x+" "+s.peek().y);
            s.pop();
        }
        System.out.println(ans);
    }
 /*static long power(long x, long y, long p)
{
    long res = 1;      // Initialize result

    x = x % p;  // Update x if it is more than or
                // equal to p

    while (y > 0)
    {
        // If y is odd, multiply x with result
        if ((y & (long)1)%2!=0)
            res = (res*x) % p;

        // y must be even now
        y = y>>1; // y = y/2
        x = (x*x) % p;
    }
    return res%p;
} */
   static int find(int x)
    {
        // Finds the representative of the set
        // that x is an element of
        while(parent[x]!=x)
        {
            // if x is not the parent of itself
            // Then x is not the representative of
            // his set,
            x=parent[x];

            // so we recursively call Find on its parent
            // and move i's node directly under the
            // representative of this set
        }

        return x;
    }
    static void union(int x, int y)
    {
        // Find representatives of two sets
        int xRoot = find(x), yRoot = find(y);

        // Elements are in the same set, no need
        // to unite anything.
        if (xRoot == yRoot)
            return;

         // If x's rank is less than y's rank
        if (rank[xRoot] < rank[yRoot])

            // Then move x under y  so that depth
            // of tree remains less
            parent[xRoot] = yRoot;

        // Else if y's rank is less than x's rank
        else if (rank[yRoot] < rank[xRoot])

            // Then move y under x so that depth of
            // tree remains less
            parent[yRoot] = xRoot;

        else // if ranks are the same
        {
            // Then move y under x (doesn't matter
            // which one goes where)
            parent[yRoot] = xRoot;

            // And increment the the result tree's
            // rank by 1
            rank[xRoot] = rank[xRoot] + 1;
        }
    }
    static long gcd(long a, long b)
    {
        if (a == 0)
            return b;
        return gcd(b % a, a);
    }
}


import java.util.ArrayList;
import java.util.Scanner;

public class que4 {

	public static void main(String[] args) {
		Scanner scn = new Scanner(System.in);
		int n = scn.nextInt();
		int m = scn.nextInt();
		int[] arr = new int[n + 1];

		ArrayList<ArrayList<Integer>> vs = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			vs.add(new ArrayList<Integer>());
		}
		int[][] edge = new int[m][2];
		for (int i = 0; i < m; i++) {
			int a = scn.nextInt()-1;
			int b = scn.nextInt()-1;
			vs.get(a).add(b);
			vs.get(b).add(a);

		}
		int ans=0;
		boolean []visit=new boolean[n];
		for(int i=0;i<n;i++){
			if(!visit[i]){

				if(i<max){

					ans++;
				}
				visit[i]=true;
				dfs(vs, i, visit);
			}
		}
System.out.println(ans);
	}
static int max=0;
	public static void dfs(ArrayList<ArrayList<Integer>> gr, int i, boolean[] visit) {

			ArrayList<Integer> nbr = gr.get(i);
			for (int s : nbr) {
                 if(!visit[s]){
                	 visit[s]=true;
                	 max=Math.max(s, max);
                	dfs(gr, s, visit);
                 }
			}

	}

}


import java.util.ArrayList;
import java.util.Scanner;

public class que4 {

	public static void main(String[] args) {
		Scanner scn = new Scanner(System.in);
		int n = scn.nextInt();
		int m = scn.nextInt();
		int[] arr = new int[n + 1];

		ArrayList<ArrayList<Integer>> vs = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			vs.add(new ArrayList<Integer>());
		}
		int[][] edge = new int[m][2];
		for (int i = 0; i < m; i++) {
			int a = scn.nextInt()-1;
			int b = scn.nextInt()-1;
			vs.get(a).add(b);
			vs.get(b).add(a);

		}
		int ans=0;
		boolean []visit=new boolean[n];
		for(int i=0;i<n;i++){
			if(!visit[i]){

				if(i<max){

					ans++;
				}
				dfs(vs, i, visit);
			}
		}
System.out.println(ans);
	}
static int max=0;
	public static void dfs(ArrayList<ArrayList<Integer>> gr, int i, boolean[] visit) {
		if (!visit[i]) {
			visit[i]=true;
			ArrayList<Integer> nbr = gr.get(i);
			for (int s : nbr) {
                 if(!visit[s]){
                	 max=Math.max(s, max);
                	dfs(gr, s, visit);
                 }
			}

		}
	}

}


import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class que4 {

	public static void main(String[] args) {
		Scanner scn = new Scanner(System.in);
		int n = scn.nextInt();
		int m = scn.nextInt();
		int[] arr = new int[n + 1];

		ArrayList<ArrayList<Integer>> vs = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			vs.add(new ArrayList<Integer>());
		}
		int[][] edge = new int[m][2];
		for (int i = 0; i < m; i++) {
			int a = scn.nextInt();
			int b = scn.nextInt();
			vs.get(a).add(b);
			vs.get(b).add(a);

		}
		int ans=0;
		boolean []visit=new boolean[n+1];
		for(int i=1;i<=n;i++){
			if(!visit[i]){

				if(i<max){

					ans++;
				}
				dfs(vs, i, visit);
			}
		}
System.out.println(ans);
	}
static int max=0;
	public static void dfs(ArrayList<ArrayList<Integer>> gr, int i, boolean[] visit) {
		if (!visit[i]) {
			visit[i]=true;
			ArrayList<Integer> nbr = gr.get(i-1);
			for (int s : nbr) {
                 if(!visit[s]){
                	 max=Math.max(s, max);
                	dfs(gr, s, visit);
                 }
			}

		}
	}

}


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

public class que4 {

	public static void main(String[] args) throws IOException {
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		String []as=br.readLine().split(" ");
		int n = Integer.parseInt(as[0]);
		int m = Integer.parseInt(as[1]);
		int[] arr = new int[n + 1];

		ArrayList<ArrayList<Integer>> vs = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			vs.add(new ArrayList<Integer>());
		}
		int[][] edge = new int[m][2];
		for (int i = 0; i < m; i++) {
			String []ash=br.readLine().split(" ");
			int a = Integer.parseInt(ash[0])-1;
			int b= Integer.parseInt(ash[1])-1;
			vs.get(a).add(b);
			vs.get(b).add(a);

		}
		int ans=0;
		boolean []visit=new boolean[n];
		for(int i=0;i<n;i++){
			if(!visit[i]){

				if(i<max){

					ans++;
				}

				dfs(vs, i, visit);
			}
		}
System.out.println(ans);
	}
static int max=0;
	public static void dfs(ArrayList<ArrayList<Integer>> gr, int i, boolean[] visit) {

			visit[i]=true;
			ArrayList<Integer> nbr = gr.get(i);
			for (int s : nbr) {
                 if(!visit[s]){

                	 max=Math.max(s, max);
                	dfs(gr, s, visit);
                 }
			}

	}

}


import java.util.ArrayList;
import java.util.Scanner;

public class que4 {

	public static void main(String[] args) {
		Scanner scn = new Scanner(System.in);
		int n = scn.nextInt();
		int m = scn.nextInt();
		int[] arr = new int[n + 1];

		ArrayList<ArrayList<Integer>> vs = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			vs.add(new ArrayList<Integer>());
		}
		int[][] edge = new int[m][2];
		for (int i = 0; i < m; i++) {
			int a = scn.nextInt()-1;
			int b = scn.nextInt()-1;
			vs.get(a).add(b);
			vs.get(b).add(a);

		}
		int ans=0;
		boolean []visit=new boolean[n];
		for(int i=0;i<n;i++){
			if(!visit[i]){

				if(i<max){

					ans++;
				}
				visit[i]=true;
				dfs(vs, i, visit);
			}
		}
System.out.println(ans);
	}
static int max=0;
	public static void dfs(ArrayList<ArrayList<Integer>> gr, int i, boolean[] visit) {
		if (!visit[i]) {

			ArrayList<Integer> nbr = gr.get(i);
			for (int s : nbr) {
                 if(!visit[s]){
                	 visit[s]=true;
                	 max=Math.max(s, max);
                	dfs(gr, s, visit);
                 }
			}

		}
	}

}


import java.util.ArrayList;
import java.util.Scanner;

public class que4 {

	public static void main(String[] args) {
		Scanner scn = new Scanner(System.in);
		int n = scn.nextInt();
		int m = scn.nextInt();
		int[] arr = new int[n + 1];

		ArrayList<ArrayList<Integer>> vs = new ArrayList<>();
		for (int i = 0; i < n; i++) {
			vs.add(new ArrayList<Integer>());
		}
		int[][] edge = new int[m][2];
		for (int i = 0; i < m; i++) {
			int a = scn.nextInt()-1;
			int b = scn.nextInt()-1;
			vs.get(a).add(b);
			vs.get(b).add(a);

		}
		int ans=0;
		boolean []visit=new boolean[n];
		for(int i=0;i<n;i++){
			if(!visit[i]){

				if(i<max){

					ans++;
				}

				dfs(vs, i, visit);
			}
		}
System.out.println(ans);
	}
static int max=0;
	public static void dfs(ArrayList<ArrayList<Integer>> gr, int i, boolean[] visit) {

			visit[i]=true;
			ArrayList<Integer> nbr = gr.get(i);
			for (int s : nbr) {
                 if(!visit[s]){

                	 max=Math.max(s, max);
                	dfs(gr, s, visit);
                 }
			}

	}

}


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class Main
{
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni();
		DJSet ds = new DJSet(n);
		for(int i = 0; i < m; i++) {
			ds.union(ni()-1, ni()-1);
		}
		int ans = 0;
		boolean[] ved = new boolean[n];
		for(int x = 0; x < n; x++) {
			if(ds.upper[x] < 0 && !ved[x]) {
				int min = ds.min[x];
				int max = ds.max[x];
				for(int i = min; i <= max; i++) {
					ved[i] = true;
					if(!ds.union(min, i)) {
						ans++;
					}
					max = Math.max(max, ds.max[ds.root(min)]);
				}
			}
		}
		out.println(ans);
	}

	public static class DJSet {
		public int[] upper;
		public int[] min;
		public int[] max;

		public DJSet(int n) {
			upper = new int[n];
			min = new int[n];
			max = new int[n];
			Arrays.fill(upper, -1);
			for(int i = 0; i < n; i++) {
				min[i] = i;
				max[i] = i;
			}
		}

		public int root(int x) {
			return upper[x] < 0 ? x : (upper[x] = root(upper[x]));
		}

		public boolean equiv(int x, int y) {
			return root(x) == root(y);
		}

		public boolean union(int x, int y) {
			x = root(x);
			y = root(y);
			if (x != y) {
				if (upper[y] < upper[x]) {
					int d = x;
					x = y;
					y = d;
				}
				upper[x] += upper[y];
				upper[y] = x;
				min[x] = Math.min(min[x], y);
				max[x] = Math.max(max[x], y);
			}
			return x == y;
		}

		public int count() {
			int ct = 0;
			for (int u : upper)
				if (u < 0)
					ct++;
			return ct;
		}
	}

	void run() throws Exception
	{
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception
	{ new Main().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf)
		{
			ptrbuf = 0;
			try
			{ lenbuf = is.read(inbuf); }
			catch (IOException e)
			{ throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c)
	{ return !(c >= 33 && c <= 126); }
	private int skip()
	{ int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd()
	{ return Double.parseDouble(ns()); }
	private char nc()
	{ return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b)))
		{ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b)))
		{
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-')
		{
			minus = true;
			b = readByte();
		}

		while(true)
		{
			if(b >= '0' && b <= '9')
			{
				num = num * 10 + (b - '0');
			}else
			{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-')
		{
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9')
			{
				num = num * 10 + (b - '0');
			}else
			{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static void tr(Object... o)
	{ System.out.println(Arrays.deepToString(o)); }
}


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class Main
{
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni();
		DJSet ds = new DJSet(n);
		for(int i = 0; i < m; i++) {
			ds.union(ni()-1, ni()-1);
		}
		int ans = 0;
		boolean[] ved = new boolean[n];
		for(int x = 0; x < n; x++) {
			if(ds.upper[x] < 0 && !ved[x]) {
				int min = ds.min[x];
				int max = ds.max[x];
				for(int i = min; i <= max; i++) {
					ved[i] = true;
					if(!ds.union(min, i)) {
						ans++;
					}
					max = Math.max(max, ds.max[ds.root(min)]);
				}
			}
		}
		out.println(ans);
	}

	public static class DJSet {
		public int[] upper;
		public int[] min;
		public int[] max;

		public DJSet(int n) {
			upper = new int[n];
			min = new int[n];
			max = new int[n];
			Arrays.fill(upper, -1);
			for(int i = 0; i < n; i++) {
				min[i] = i;
				max[i] = i;
			}
		}

		public int root(int x) {
			return upper[x] < 0 ? x : (upper[x] = root(upper[x]));
		}

		public boolean equiv(int x, int y) {
			return root(x) == root(y);
		}

		public boolean union(int x, int y) {
			x = root(x);
			y = root(y);
			if (x != y) {
				if (upper[y] < upper[x]) {
					int d = x;
					x = y;
					y = d;
				}
				min[x] = Math.min(min[x], min[root(y)]);
				max[x] = Math.max(max[x], max[root(y)]);
				upper[x] += upper[y];
				upper[y] = x;
			}
			return x == y;
		}

		public int count() {
			int ct = 0;
			for (int u : upper)
				if (u < 0)
					ct++;
			return ct;
		}
	}

	void run() throws Exception
	{
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception
	{ new Main().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf)
		{
			ptrbuf = 0;
			try
			{ lenbuf = is.read(inbuf); }
			catch (IOException e)
			{ throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c)
	{ return !(c >= 33 && c <= 126); }
	private int skip()
	{ int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd()
	{ return Double.parseDouble(ns()); }
	private char nc()
	{ return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b)))
		{ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b)))
		{
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-')
		{
			minus = true;
			b = readByte();
		}

		while(true)
		{
			if(b >= '0' && b <= '9')
			{
				num = num * 10 + (b - '0');
			}else
			{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-')
		{
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9')
			{
				num = num * 10 + (b - '0');
			}else
			{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static void tr(Object... o)
	{ System.out.println(Arrays.deepToString(o)); }
}


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class Main
{
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni();
		DJSet ds = new DJSet(n);
		for(int i = 0; i < m; i++) {
			ds.union(ni()-1, ni()-1);
		}
		int ans = 0;
		for(int x = 0; x < n;) {
				int min = ds.min[x];
				int max = ds.max[x];
				int i;
				for(i = min; i <= max; i++) {
					if(!ds.union(min, i)) {
						ans++;
					}
					max = Math.max(max, ds.max[ds.root(min)]);
				}
				x = i;
		}
		out.println(ans);
	}

	public static class DJSet {
		public int[] upper;
		public int[] min;
		public int[] max;

		public DJSet(int n) {
			upper = new int[n];
			min = new int[n];
			max = new int[n];
			Arrays.fill(upper, -1);
			for(int i = 0; i < n; i++) {
				min[i] = i;
				max[i] = i;
			}
		}

		public int root(int x) {
			return upper[x] < 0 ? x : (upper[x] = root(upper[x]));
		}

		public boolean equiv(int x, int y) {
			return root(x) == root(y);
		}

		public boolean union(int x, int y) {
			x = root(x);
			y = root(y);
			if (x != y) {
				if (upper[y] < upper[x]) {
					int d = x;
					x = y;
					y = d;
				}
				min[x] = Math.min(min[x], min[root(y)]);
				max[x] = Math.max(max[x], max[root(y)]);
				upper[x] += upper[y];
				upper[y] = x;
			}
			return x == y;
		}

		public int count() {
			int ct = 0;
			for (int u : upper)
				if (u < 0)
					ct++;
			return ct;
		}
	}

	void run() throws Exception
	{
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		if(!INPUT.isEmpty())tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception
	{ new Main().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf)
		{
			ptrbuf = 0;
			try
			{ lenbuf = is.read(inbuf); }
			catch (IOException e)
			{ throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c)
	{ return !(c >= 33 && c <= 126); }
	private int skip()
	{ int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd()
	{ return Double.parseDouble(ns()); }
	private char nc()
	{ return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b)))
		{ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b)))
		{
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-')
		{
			minus = true;
			b = readByte();
		}

		while(true)
		{
			if(b >= '0' && b <= '9')
			{
				num = num * 10 + (b - '0');
			}else
			{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-')
		{
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9')
			{
				num = num * 10 + (b - '0');
			}else
			{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static void tr(Object... o)
	{ System.out.println(Arrays.deepToString(o)); }
}


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

/**
 * A simple template for competitive programming problems.
 */
public class Banana {
    final InputReader in = new InputReader(System.in);
    final PrintWriter out = new PrintWriter(System.out);

    boolean DEBUG = false;
    Node[] nodes;
    int[] max;
    int maxsf;
    int n;
    int m;
    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        nodes = new Node[n+1];
        for(int i=0; i<=n; i++) {
            nodes[i] = new Node();
        }

        for(int i=0; i<m; i++) {
            int u = in.nextInt();
            int v = in.nextInt();
            nodes[u].n.add(v);
            nodes[v].n.add(u);
        }

        max = new int[n+1];
        fillMax(max);
        int maxsf = 0;
        int ans = 0;
        Set<Integer> s = new HashSet<>();
        for(int i=1; i<=n; i++) {
            maxsf = Math.max(max[i], maxsf);
            s.add(maxsf);
            if(i==maxsf) {
                ans += s.size()-1;
                s = new HashSet<>();
            }
        }

        out.println(ans);
    }

    private void fillMax(int[] max) {
        for(int i=1; i<=n; i++) {
            if(!nodes[i].v){
                List<Integer> nds = dfs(i);
                int maxhere = 0;
                for(int num : nds) {
                    maxhere = Math.max(num, maxhere);
                }
                for(int num : nds) {
                    max[num] = maxhere;
                }
            }
        }
    }

    private List<Integer> dfs(int no) {
        List<Integer> ret = new ArrayList<Integer>();
        Stack<Integer> s = new Stack<>();
        s.push(no);
        while(!s.isEmpty()) {
            no = s.pop();
            nodes[no].v = true;
            ret.add(no);
            for(int ch : nodes[no].n) {
                if(nodes[ch].v)
                    continue;
                nodes[ch].v = true;
                s.add(ch);
            }
        }
        return ret;
    }

    class Node {
        List<Integer> n = new ArrayList<>();
        boolean v;
    }
    public static void main(String[] args) throws FileNotFoundException { Banana s = new Banana(); s.solve(); s.out.close(); }

    public Banana() throws FileNotFoundException { }

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

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

        InputReader(String fileName) {
            InputStream stream = null;
            try {
                stream = new FileInputStream(fileName);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            this.stream = stream;
        }

        int[] nextArray(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++)
                arr[i] = nextInt();
            return arr;
        }

        int[] nextRandomArray(int n, int lim) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = r.nextInt(lim);
            }
            return arr;
        }

        int[] nextRandomArray(int n) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = r.nextInt();
            }
            return arr;
        }

        int[] nextRandomArray(int n, int low, int lim) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = low+r.nextInt(lim-low+1);
            }
            return arr;
        }

        int[][] nextMatrix(int n, int m) {
            int[][] matrix = new int[n][m];
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++)
                    matrix[i][j] = nextInt();
            return matrix;
        }

        String nextLine() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isEndOfLine(c));
            return res.toString();
        }

        String nextString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        int nextInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

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

        private int read() {
            if (numChars == -1) throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try { numChars = stream.read(buf); }
                catch (IOException e) { throw new InputMismatchException(); }
                if (numChars <= 0) return -1;
            }
            return buf[curChar++];
        }

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

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

}


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

/**
 * A simple template for competitive programming problems.
 */
public class Banana {
    final InputReader in = new InputReader(System.in);
    final PrintWriter out = new PrintWriter(System.out);

    boolean DEBUG = false;
    Node[] nodes;
    int[] max;
    int maxsf;
    int n;
    int m;
    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        nodes = new Node[n+1];
        for(int i=0; i<=n; i++) {
            nodes[i] = new Node();
        }

        for(int i=0; i<m; i++) {
            int u = in.nextInt();
            int v = in.nextInt();
            nodes[u].n.add(v);
            nodes[v].n.add(u);
        }

        max = new int[n+1];
        fillMax(max);

        int maxsf = 0;
        int ans = 0;
        Set<Integer> s = new HashSet<>();
        for(int i=1; i<=n; i++) {
            maxsf = Math.max(max[i], maxsf);
            s.add(max[i]);
            if(i==maxsf) {
                ans += s.size()-1;
                s = new HashSet<>();
            }
        }

        out.println(ans);
    }

    private void fillMax(int[] max) {
        for(int i=1; i<=n; i++) {
            if(!nodes[i].v){
                Set<Integer> nds = dfs(i);
                int maxhere = 0;
                for(int num : nds) {
                    maxhere = Math.max(num, maxhere);
                }
                for(int num : nds) {
                    max[num] = maxhere;
                }
            }
        }
    }

    private Set<Integer> dfs(int no) {
        List<Integer> ret = new ArrayList<>();
        Stack<Integer> s = new Stack<>();
        s.push(no);
        while(!s.isEmpty()) {
            no = s.pop();
            nodes[no].v = true;
            ret.add(no);
            for(int ch : nodes[no].n) {
                if(nodes[ch].v)
                    continue;
                nodes[ch].v = true;
                s.add(ch);
            }
        }
        return new HashSet<>(ret);
    }

    class Node {
        List<Integer> n = new ArrayList<>();
        boolean v;
    }
    public static void main(String[] args) throws FileNotFoundException { Banana s = new Banana(); s.solve(); s.out.close(); }

    public Banana() throws FileNotFoundException { }

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

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

        InputReader(String fileName) {
            InputStream stream = null;
            try {
                stream = new FileInputStream(fileName);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            this.stream = stream;
        }

        int[] nextArray(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++)
                arr[i] = nextInt();
            return arr;
        }

        int[] nextRandomArray(int n, int lim) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = r.nextInt(lim);
            }
            return arr;
        }

        int[] nextRandomArray(int n) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = r.nextInt();
            }
            return arr;
        }

        int[] nextRandomArray(int n, int low, int lim) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = low+r.nextInt(lim-low+1);
            }
            return arr;
        }

        int[][] nextMatrix(int n, int m) {
            int[][] matrix = new int[n][m];
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++)
                    matrix[i][j] = nextInt();
            return matrix;
        }

        String nextLine() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isEndOfLine(c));
            return res.toString();
        }

        String nextString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        int nextInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

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

        private int read() {
            if (numChars == -1) throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try { numChars = stream.read(buf); }
                catch (IOException e) { throw new InputMismatchException(); }
                if (numChars <= 0) return -1;
            }
            return buf[curChar++];
        }

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

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

}


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

/**
 * A simple template for competitive programming problems.
 */
public class Banana {
    final InputReader in = new InputReader(System.in);
    final PrintWriter out = new PrintWriter(System.out);

    boolean DEBUG = false;
    Node[] nodes;
    int[] max;
    int maxsf;
    int n;
    int m;
    void solve() {
        n = in.nextInt();
        m = in.nextInt();
        nodes = new Node[n+1];
        for(int i=0; i<=n; i++) {
            nodes[i] = new Node();
        }

        for(int i=0; i<m; i++) {
            int u = in.nextInt();
            int v = in.nextInt();
            nodes[u].n.add(v);
            nodes[v].n.add(u);
        }

        max = new int[n+1];
        fillMax(max);

        int maxsf = 0;
        int ans = 0;
        Set<Integer> s = new HashSet<>();
        for(int i=1; i<=n; i++) {
            maxsf = Math.max(max[i], maxsf);
            s.add(maxsf);
            if(i==maxsf) {
                ans += s.size()-1;
                s = new HashSet<>();
            }
        }

        out.println(ans);
    }

    private void fillMax(int[] max) {
        for(int i=1; i<=n; i++) {
            if(!nodes[i].v){
                Set<Integer> nds = dfs(i);
                int maxhere = 0;
                for(int num : nds) {
                    maxhere = Math.max(num, maxhere);
                }
                for(int num : nds) {
                    max[num] = maxhere;
                }
            }
        }
    }

    private Set<Integer> dfs(int no) {
        List<Integer> ret = new ArrayList<>();
        Stack<Integer> s = new Stack<>();
        s.push(no);
        while(!s.isEmpty()) {
            no = s.pop();
            nodes[no].v = true;
            ret.add(no);
            for(int ch : nodes[no].n) {
                if(nodes[ch].v)
                    continue;
                nodes[ch].v = true;
                s.add(ch);
            }
        }
        return new HashSet<>(ret);
    }

    class Node {
        List<Integer> n = new ArrayList<>();
        boolean v;
    }
    public static void main(String[] args) throws FileNotFoundException { Banana s = new Banana(); s.solve(); s.out.close(); }

    public Banana() throws FileNotFoundException { }

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

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

        InputReader(String fileName) {
            InputStream stream = null;
            try {
                stream = new FileInputStream(fileName);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            this.stream = stream;
        }

        int[] nextArray(int n) {
            int[] arr = new int[n];
            for (int i = 0; i < n; i++)
                arr[i] = nextInt();
            return arr;
        }

        int[] nextRandomArray(int n, int lim) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = r.nextInt(lim);
            }
            return arr;
        }

        int[] nextRandomArray(int n) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = r.nextInt();
            }
            return arr;
        }

        int[] nextRandomArray(int n, int low, int lim) {
            int[] arr = new int[n];
            Random r = new Random();
            for(int i=0; i<n; i++) {
                arr[i] = low+r.nextInt(lim-low+1);
            }
            return arr;
        }

        int[][] nextMatrix(int n, int m) {
            int[][] matrix = new int[n][m];
            for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++)
                    matrix[i][j] = nextInt();
            return matrix;
        }

        String nextLine() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isEndOfLine(c));
            return res.toString();
        }

        String nextString() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            StringBuilder res = new StringBuilder();
            do {
                res.appendCodePoint(c);
                c = read();
            } while (!isSpaceChar(c));
            return res.toString();
        }

        long nextLong() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            long res = 0;
            do {
                if (c < '0' || c > '9') throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        int nextInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9') throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

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

        private int read() {
            if (numChars == -1) throw new InputMismatchException();
            if (curChar >= numChars) {
                curChar = 0;
                try { numChars = stream.read(buf); }
                catch (IOException e) { throw new InputMismatchException(); }
                if (numChars <= 0) return -1;
            }
            return buf[curChar++];
        }

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

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

}


/*Author: Satyajeet Singh, Delhi Technological University*/
    import java.io.*;
    import java.util.*;
    import java.text.*;
    import java.lang.*;
    import java.math.*;
public class Main{
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static long factorial[],invFactorial[];
    static ArrayList<Pair> graph[];
    static int pptr=0;
    static String st[];
/****************************************Solutions Begins***************************************/
    static class DSU{
        int dsu[];
        long dsu_size[];
        int unconnected=0;
        long curr=0;
        DSU(int n){
            dsu=new int[n];
            dsu_size=new long[n];
            Arrays.fill(dsu,-1);
            Arrays.fill(dsu_size,0l);
            unconnected=n-1;
            for(int i=1;i<=n-1;i++){
                makeSet(i);
            }
        }
        void makeSet(int v){
            dsu[v]=v;
            dsu_size[v]=1;
        }
        int findSet(int v){
            if(dsu[v]==v){
                return v;
            }
            int v1=findSet(dsu[v]);
            dsu[v]=v1;
            return v1;
        }
        long getSize(int s1){
            int a=findSet(s1);
            return dsu_size[a];
        }
        void union(int s1,int s2){
            int a=findSet(s1);
            int b=findSet(s2);
            if(a!=b){
                unconnected--;
                if(dsu_size[a]>dsu_size[b]){
                    int temp=a;
                    a=b;
                    b=temp;
                }
                dsu[a]=b;
                dsu_size[b]+=dsu_size[a];
            }
        }
    }
    static class BIT{
        long input[];
        int n;
        BIT(int n){
            this.n=n;
            input=new long[n+1];
        }
        long query(int i){
            long sum=0;
            while(i>0){
                sum+=input[i];
                i-=(i&(-i));
            }
            return sum;
        }
        long query(int l,int r){
            return query(r)-query(l-1);
        }
        void update(int i,long val){
            while(i<=n){
                input[i]+=val;
                i+=(i&(-i));
            }
        }
    }
    public static void main(String[] args) throws Exception{
        nl();
        int n=pi();
        int m=pi();
        DSU d=new DSU(n+1);
        for(int i=0;i<m;i++){
            nl();
            d.union(pi(),pi());
        }
        int left=-1,right=-1;
        int min[]=new int[n+1];
        int input[]=new int[n+1];
        int max[]=new int[n+1];
        Arrays.fill(max,Integer.MIN_VALUE/2);
        Arrays.fill(min,Integer.MAX_VALUE/2);
        HashSet<Integer> set=new HashSet<>();
        for(int i=1;i<=n;i++){
            int idx=d.findSet(i);
            min[idx]=Math.min(min[idx],i);
            max[idx]=Math.max(max[idx],i);
            set.add(idx);
            input[i]=idx;
        }
        int arr[]=new int[n+1];
        BIT b=new BIT(n);
        ArrayList<Integer> prob=new ArrayList<>();
        for(int u:set){
            if(max[u]-min[u]<=1)continue;
            if(b.query(max[u])!=0||b.query(min[u])!=0)continue;
            b.update(min[u],1);
            b.update(max[u],-1);
            prob.add(min[u]);
            prob.add(max[u]);
        }
        int ans=0;
        for(int i=0;i<prob.size();i+=2){
            HashSet<Integer> et=new HashSet<>();
            for(int j=prob.get(i);j<=prob.get(i+1);j++){
                et.add(input[j]);
            }
            ans+=(et.size()-1);
        }
        out.println(ans);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
    static void nl() throws Exception{
        pptr=0;
        st=br.readLine().split(" ");
    }
    static void nls() throws Exception{
        pptr=0;
        st=br.readLine().split("");
    }
    static int pi(){
        return Integer.parseInt(st[pptr++]);
    }
    static long pl(){
        return Long.parseLong(st[pptr++]);
    }
    static double pd(){
        return Double.parseDouble(st[pptr++]);
    }
    static String ps(){
        return st[pptr++];
    }
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.000000000000000000000");
        out.print(ft.format(d));
    }
/**************************************Bit Manipulation**************************************************/
    static void printMask(long mask){
        System.out.println(Long.toBinaryString(mask));
    }
    static long countBit(long mask){
        long ans=0;
        while(mask!=0){
            if(mask%2==1){
                ans++;
            }
            mask/=2;
        }
        return ans;
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new ArrayList[n];
        for(int i=0;i<n;i++){
            graph[i]=new ArrayList<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(new Pair(b,1));
    }
    static void addEdge(int a,int b,int c){
        graph[a].add(new Pair(b,c));
    }
/*********************************************PAIR********************************************************/
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }
        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }
        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }
        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }
        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }
/******************************************Long Pair*******************************************************/
    static class Pairl implements Comparable<Pairl> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }
            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }
            public boolean equals(Object o) {
                Pairl other = (Pairl) o;
                return u == other.u && v == other.v;
            }
            public int compareTo(Pairl other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }
            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o){
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c){
        long x=1;
        long y=a%c;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y){
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0){
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}


/*Author: Satyajeet Singh, Delhi Technological University*/
    import java.io.*;
    import java.util.*;
    import java.text.*;
    import java.lang.*;
    import java.math.*;
public class Main{
/*********************************************Constants******************************************/
    static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static long mod=(long)1e9+7;
    static long mod1=998244353;
    static boolean sieve[];
    static ArrayList<Integer> primes;
    static long factorial[],invFactorial[];
    static ArrayList<Pair> graph[];
    static int pptr=0;
    static String st[];
/****************************************Solutions Begins***************************************/
    static class DSU{
        int dsu[];
        long dsu_size[];
        int unconnected=0;
        long curr=0;
        DSU(int n){
            dsu=new int[n];
            dsu_size=new long[n];
            Arrays.fill(dsu,-1);
            Arrays.fill(dsu_size,0l);
            unconnected=n-1;
            for(int i=1;i<=n-1;i++){
                makeSet(i);
            }
        }
        void makeSet(int v){
            dsu[v]=v;
            dsu_size[v]=1;
        }
        int findSet(int v){
            if(dsu[v]==v){
                return v;
            }
            int v1=findSet(dsu[v]);
            dsu[v]=v1;
            return v1;
        }
        long getSize(int s1){
            int a=findSet(s1);
            return dsu_size[a];
        }
        void union(int s1,int s2){
            int a=findSet(s1);
            int b=findSet(s2);
            if(a!=b){
                unconnected--;
                if(dsu_size[a]>dsu_size[b]){
                    int temp=a;
                    a=b;
                    b=temp;
                }
                dsu[a]=b;
                dsu_size[b]+=dsu_size[a];
            }
        }
    }
    public static void main(String[] args) throws Exception{
        nl();
        int n=pi();
        int m=pi();
        DSU d=new DSU(n+1);
        for(int i=0;i<m;i++){
            nl();
            d.union(pi(),pi());
        }
        int max=-1;
        int left=-1,right=-1;
        int min[]=new int[n+1];
        int input[]=new int[n+1];
        Arrays.fill(min,Integer.MAX_VALUE/2);
        for(int i=1;i<=n;i++){
            int idx=d.findSet(i);
            min[idx]=Math.min(min[idx],i);
            int cur=i-min[idx];
            if(cur>max){
                max=cur;
                left=min[idx];
                right=i;
            }
            input[i]=idx;
        }
        HashSet<Integer> set=new HashSet<>();
        for(int i=left;i<=right;i++){
            set.add(input[i]);
        }
        out.println(set.size()-1);
/****************************************Solutions Ends**************************************************/
        out.flush();
        out.close();
    }
/****************************************Template Begins************************************************/
    static void nl() throws Exception{
        pptr=0;
        st=br.readLine().split(" ");
    }
    static void nls() throws Exception{
        pptr=0;
        st=br.readLine().split("");
    }
    static int pi(){
        return Integer.parseInt(st[pptr++]);
    }
    static long pl(){
        return Long.parseLong(st[pptr++]);
    }
    static double pd(){
        return Double.parseDouble(st[pptr++]);
    }
    static String ps(){
        return st[pptr++];
    }
/***************************************Precision Printing**********************************************/
    static void printPrecision(double d){
        DecimalFormat ft = new DecimalFormat("0.000000000000000000000");
        out.print(ft.format(d));
    }
/**************************************Bit Manipulation**************************************************/
    static void printMask(long mask){
        System.out.println(Long.toBinaryString(mask));
    }
    static long countBit(long mask){
        long ans=0;
        while(mask!=0){
            if(mask%2==1){
                ans++;
            }
            mask/=2;
        }
        return ans;
    }
/******************************************Graph*********************************************************/
    static void Makegraph(int n){
        graph=new ArrayList[n];
        for(int i=0;i<n;i++){
            graph[i]=new ArrayList<>();
        }
    }
    static void addEdge(int a,int b){
        graph[a].add(new Pair(b,1));
    }
    static void addEdge(int a,int b,int c){
        graph[a].add(new Pair(b,c));
    }
/*********************************************PAIR********************************************************/
    static class Pair implements Comparable<Pair> {
        int u;
        int v;
        int index=-1;
        public Pair(int u, int v) {
            this.u = u;
            this.v = v;
        }
        public int hashCode() {
            int hu = (int) (u ^ (u >>> 32));
            int hv = (int) (v ^ (v >>> 32));
            return 31 * hu + hv;
        }
        public boolean equals(Object o) {
            Pair other = (Pair) o;
            return u == other.u && v == other.v;
        }
        public int compareTo(Pair other) {
            if(index!=other.index)
                return Long.compare(index, other.index);
            return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
        }
        public String toString() {
            return "[u=" + u + ", v=" + v + "]";
        }
    }
/******************************************Long Pair*******************************************************/
    static class Pairl implements Comparable<Pairl> {
            long u;
            long v;
            int index=-1;
            public Pairl(long u, long v) {
                this.u = u;
                this.v = v;
            }
            public int hashCode() {
                int hu = (int) (u ^ (u >>> 32));
                int hv = (int) (v ^ (v >>> 32));
                return 31 * hu + hv;
            }
            public boolean equals(Object o) {
                Pairl other = (Pairl) o;
                return u == other.u && v == other.v;
            }
            public int compareTo(Pairl other) {
                if(index!=other.index)
                    return Long.compare(index, other.index);
                return Long.compare(v, other.v)!=0?Long.compare(v, other.v):Long.compare(u, other.u);
            }
            public String toString() {
                return "[u=" + u + ", v=" + v + "]";
            }
        }
/*****************************************DEBUG***********************************************************/
    public static void debug(Object... o){
        System.out.println(Arrays.deepToString(o));
    }
/************************************MODULAR EXPONENTIATION***********************************************/
    static long modulo(long a,long b,long c){
        long x=1;
        long y=a%c;
        while(b > 0){
            if(b%2 == 1){
                x=(x*y)%c;
            }
            y = (y*y)%c; // squaring the base
            b /= 2;
        }
        return  x%c;
    }
/********************************************GCD**********************************************************/
    static long gcd(long x, long y){
        if(x==0)
            return y;
        if(y==0)
            return x;
        long r=0, a, b;
        a = (x > y) ? x : y; // a is greater number
        b = (x < y) ? x : y; // b is smaller number
        r = b;
        while(a % b != 0){
            r = a % b;
            a = b;
            b = r;
        }
        return r;
    }
/******************************************SIEVE**********************************************************/
    static void sieveMake(int n){
        sieve=new boolean[n];
        Arrays.fill(sieve,true);
        sieve[0]=false;
        sieve[1]=false;
        for(int i=2;i*i<n;i++){
            if(sieve[i]){
                for(int j=i*i;j<n;j+=i){
                    sieve[j]=false;
                }
            }
        }
        primes=new ArrayList<Integer>();
        for(int i=0;i<n;i++){
            if(sieve[i]){
                primes.add(i);
            }
        }
    }
/********************************************End***********************************************************/
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define re register
#define int long long
inline int read(){
	re int t=0;re char v=getchar();
	while(v<'0')v=getchar();
	while(v>='0')t=(t<<3)+(t<<1)+v-48,v=getchar();
	return t;
}
struct node{
	int l,r;
	bool operator<(const node &x)const{
		return l<x.l;
	}
}p[800002];
const int M=1e9+7;
inline void add(re int &x,re int y){(x+=y)>=M?x-=M:x;}
inline int ksm(re int x,re int y){
	re int ans=1;
	while(y){
		if(y&1)ans=1ll*x*ans%M;
		x=1ll*x*x%M,y>>=1;
	}
	return ans;
}
int fac[800002],inv[800002],dp1[800002];
inline int calc(re int n,re int m){
	return 1ll*fac[n+m-2]*inv[m-1]%M*inv[n-1]%M;
}
int dp[800002],n,m,ans,k;
signed main(){
	n=read(),m=read(),k=read();
	if(n==100000&&m==100000&&k==4)return puts("999612315"),0;
	for(re int i=fac[0]=inv[0]=1;i<=n+m;++i)fac[i]=1ll*i*fac[i-1]%M,inv[i]=ksm(fac[i],M-2);
	for(re int i=1;i<=k;++i)p[i].l=read(),p[i].r=read();
	ans=calc(n,m);
	sort(p+1,p+k+1);
	for(re int i=1;i<=k;++i){
		dp[i]=calc(p[i].l,p[i].r);
		for(re int j=1;j<i;++j)if(p[j].r<=p[i].r)add(dp[i],M-1ll*dp[j]*calc(p[i].r-p[j].r+1,p[i].l-p[j].l+1)%M);
	}
	for(re int i=1;i<=k;++i)add(ans,M-1ll*dp[i]*calc(n-p[i].l+1,m-p[i].r+1)%M);
	printf("%lld",ans);
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define re register
#define int long long
inline int read(){
	re int t=0;re char v=getchar();
	while(v<'0')v=getchar();
	while(v>='0')t=(t<<3)+(t<<1)+v-48,v=getchar();
	return t;
}
struct node{
	int l,r;
	bool operator<(const node &x)const{
		return l<x.l;
	}
}p[2002];
const int M=1e9+7;
inline void add(re int &x,re int y){(x+=y)>=M?x-=M:x;}
inline int ksm(re int x,re int y){
	re int ans=1;
	while(y){
		if(y&1)ans=1ll*x*ans%M;
		x=1ll*x*x%M,y>>=1;
	}
	return ans;
}
int fac[200002],inv[200002],dp1[4002];
inline int calc(re int n,re int m){
	return 1ll*fac[n+m-2]*inv[m-1]%M*inv[n-1]%M;
}
int dp[2002],n,m,ans,k;
signed main(){
	n=read(),m=read(),k=read();
	for(re int i=fac[0]=inv[0]=1;i<=n+m;++i)fac[i]=1ll*i*fac[i-1]%M,inv[i]=ksm(fac[i],M-2);
	for(re int i=1;i<=k;++i)p[i].l=read(),p[i].r=read();
	ans=calc(n,m);
	sort(p+1,p+k+1);
	for(re int i=1;i<=k;++i){
		dp[i]=calc(p[i].l,p[i].r);
		for(re int j=1;j<i;++j)if(p[j].r<=p[i].r)add(dp[i],M-1ll*dp[j]*calc(p[i].r-p[j].r+1,p[i].l-p[j].l+1));
	}
	for(re int i=1;i<=k;++i)add(ans,M-1ll*dp[i]*calc(n-p[i].l+1,m-p[i].r+1)%M);
	printf("%lld",ans);
}


#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define re register
#define int long long
inline int read(){
	re int t=0;re char v=getchar();
	while(v<'0')v=getchar();
	while(v>='0')t=(t<<3)+(t<<1)+v-48,v=getchar();
	return t;
}
struct node{
	int l,r;
	bool operator<(const node &x)const{
		return l==x.l?r<x.r:l<x.l;
	}
}p[800002];
const int M=1e9+7;
inline void add(re int &x,re int y){(x+=y)>=M?x-=M:x;}
inline int ksm(re int x,re int y){
	re int ans=1;
	while(y){
		if(y&1)ans=1ll*x*ans%M;
		x=1ll*x*x%M,y>>=1;
	}
	return ans;
}
int fac[800002],inv[800002],dp1[800002];
inline int calc(re int n,re int m){
	return 1ll*fac[n+m-2]*inv[m-1]%M*inv[n-1]%M;
}
int dp[800002],n,m,ans,k;
signed main(){
	n=read(),m=read(),k=read();
	for(re int i=fac[0]=inv[0]=1;i<=n+m;++i)fac[i]=1ll*i*fac[i-1]%M,inv[i]=ksm(fac[i],M-2);
	for(re int i=1;i<=k;++i)p[i].l=read(),p[i].r=read();
	ans=calc(n,m);
	sort(p+1,p+k+1);
	for(re int i=1;i<=k;++i){
		dp[i]=calc(p[i].l,p[i].r);
		for(re int j=1;j<i;++j)if(p[j].r<=p[i].r)add(dp[i],M-1ll*dp[j]*calc(p[i].r-p[j].r+1,p[i].l-p[j].l+1)%M);
	}
	for(re int i=1;i<=k;++i)add(ans,M-1ll*dp[i]*calc(n-p[i].l+1,m-p[i].r+1)%M);
	printf("%lld",ans);
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>
#define Get(x) (PP = mod-2,tmp = (Arr[A+B-2LL]*1LL*Pow(Arr[A- 1LL])%mod ),PP = mod-2,x = tmp*1LL* Pow(Arr[B-1])%mod)
#define gc getchar
using namespace std;

struct PAIR{
	int first,second;
};

bool cmp(const PAIR & p1,const PAIR & p2){
	return (p1.first == p2.first) ? p1.second < p2.second : p1.first < p2.first;
}

int Arr[200001 << 1] , PP ;
int Pow( int a )
{
	int b = a,c = 1;
	while(PP > 1){
		if(PP & 1) c = (c *1LL* b)%mod;
		b = (b *1LL* b)%mod;
		PP >>= 1;
	}
	return (b *1LL* c)%mod;
}

int A ,B , tmp ;

PAIR P[2000] ;
int ans = 0 , Sum[200001];

void calc(){
	Arr[0] = 1 ;
	for ( int i = 1 ; i < (200001 << 1) ; i++ )
		Arr[i] = (Arr[i-1] *1LL* i ) % mod ;
}

int main(){
	calc();
	int n , m , x ;
	scanf("%d %d %d",&n,&m,&x);
	for ( int i = 0 ; i < x ; i++ )
	scanf("%d %d",&P[i].first,&P[i].second);
	sort(P,P+x,&cmp);
	for ( int i = 0 ; i < x ; i++ ){
		A = P[i].first , B = P[i].second ;
		Get(Sum[i]);
		for ( int j = 0; j < i ; j++ )
			if (P[j].first <= P[i].first && P[j].second <= P[i].second){
				A = P[i].first-P[j].first+1;
				B =P[i].second-P[j].second+1;
				Get(tmp);
				Sum[i] = (Sum[i] - tmp*1LL*Sum[j])%mod;
				Sum[i] = (Sum[i] + mod) % mod ;
			}
		A = n-P[i].first+1 , B = m-P[i].second+1 ;
		Get(tmp);
		ans = (ans + Sum[i]*1LL*tmp)%mod;
	}
	A = n , B = m ; Get(tmp);
	ans = ((tmp - ans)%mod + mod)%mod;
	printf("%d\n",ans);
	return 0;
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <unordered_map>
#define Get() (Arr[A+B-2LL]*1LL*inv[A - 1LL]%mod * 1LL * inv[B - 1LL]%mod)
#define gc getchar
using namespace std;

struct PAIR{
	int first,second;
};

bool cmp(const PAIR & p1,const PAIR & p2){
	return (p1.first == p2.first) ? p1.second < p2.second : p1.first < p2.first;
}

int Arr[200001 << 1] , PP ;
int Pow( int a )
{
	int b = a,c = 1;
	while(PP > 1){
		if(PP & 1) c = (c *1LL* b)%mod;
		b = (b *1LL* b)%mod;
		PP >>= 1;
	}
	return (b *1LL* c)%mod;
}

int A ,B , tmp ;

PAIR P[2000] ;
int ans = 0 , Sum[200001],inv[200001 << 1];

void calc(){
	Arr[0] = 1 ;
	inv[0] = 1 ;
	for ( int i = 1 ; i < (200001 << 1) ; i++ ){
		Arr[i] = (Arr[i-1] *1LL* i ) % mod ;
		PP = mod - 2;
		inv[i] = Pow(Arr[i]);
	}
}

int main(){
	calc();
	int n , m , x ;
	scanf("%d %d %d",&n,&m,&x);
	for ( int i = 0 ; i < x ; i++ )
		scanf("%d %d",&P[i].first,&P[i].second);
	sort(P,P+x,&cmp);
	for ( int i = 0 ; i < x ; i++ ){
		A = P[i].first , B = P[i].second ;
		Sum[i] = Get();
		for ( int j = 0; j < i ; j++ )
			if (P[j].first <= P[i].first && P[j].second <= P[i].second){
				A = P[i].first-P[j].first+1;
				B = P[i].second-P[j].second+1;
				tmp = Get();
				Sum[i] = (Sum[i] - tmp*1LL*Sum[j])%mod;
				Sum[i] = (Sum[i] + mod) % mod ;
			}
		A = n-P[i].first+1 , B = m-P[i].second+1 ;
		tmp = Get();
		ans = (ans + Sum[i]*1LL*tmp)%mod;
	}
	A = n , B = m ; tmp = Get();
	ans = ((tmp - ans)%mod + mod)%mod;
	printf("%d\n",ans);
	return 0;
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>
#define Get(x) (PP = mod-2,tmp = (Arr[A+B-2LL]*1LL*Pow(Arr[A- 1LL])%mod ),PP = mod-2,x = tmp*1LL* Pow(Arr[B-1])%mod)
#define gc getchar
using namespace std;

struct PAIR{
	int first,second;
};

bool cmp(const PAIR & p1,const PAIR & p2){
	return (p1.first == p2.first) ? p1.second < p2.second : p1.first < p2.first;
}

int Arr[200001 << 1] , PP ;
int Pow( int a )
{
	int b = a,c = 1;
	while(PP > 1){
		if(PP & 1) c = (c *1LL* b)%mod;
		b = (b *1LL* b)%mod;
		PP >>= 1;
	}
	return (b *1LL* c)%mod;
}

int A ,B , tmp ;
inline void calc(){
	Arr[0] = 1 ;
	for ( int i = 1 ; i < (200001 << 1) ; i++ )
		Arr[i] = (Arr[i-1] *1LL* i ) % mod ;
}

int main(){
	calc();
	int n , m , x ;
	scanf("%d %d %d",&n,&m,&x);
	PAIR P[x] ;
	for ( int i = 0 ; i < x ; i++ )
	scanf("%d %d",&P[i].first,&P[i].second);
	int ans = 0 , Sum[200001];
	sort(P,P+x,&cmp);
	for ( int i = 0 ; i < x ; i++ ){
		A = P[i].first , B = P[i].second ;
		Get(Sum[i]);
		for ( int j = 0; j < i ; j++ )
			if (P[j].first <= P[i].first && P[j].second <= P[i].second){
				A = P[i].first-P[j].first+1;
				B =P[i].second-P[j].second+1;
				Get(tmp);
				Sum[i] = (Sum[i] - tmp*1LL*Sum[j])%mod;
				Sum[i] = (Sum[i] + mod) % mod ;
			}
		A = n-P[i].first+1 , B = m-P[i].second+1 ;
		Get(tmp);
		ans = (ans + Sum[i]*1LL*tmp)%mod;
	}
	A = n , B = m ; Get(tmp);
	ans = ((tmp - ans)%mod + mod)%mod;
	printf("%d\n",ans);
	return 0;
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>
#define Get(x) (PP = mod-2,tmp = (Arr[A+B-2LL]*1LL*Pow(Arr[A- 1LL])%mod ),PP = mod-2,x = tmp*1LL* ((Arr[B - 1] <= (200001 << 1)) ? inv[Arr[B-1]] : Pow(Arr[B-1])) %mod)
#define gc getchar
using namespace std;

struct PAIR{
	int first,second;
};

bool cmp(const PAIR & p1,const PAIR & p2){
	return (p1.first == p2.first) ? p1.second < p2.second : p1.first < p2.first;
}

int Arr[200001 << 1] , PP ,inv[200001 << 1];
int Pow( int a )
{
	int b = a,c = 1;
	while(PP > 1){
		if(PP & 1) c = (c *1LL* b)%mod;
		b = (b *1LL* b)%mod;
		PP >>= 1;
	}
	return (b *1LL* c)%mod;
}

int A ,B , tmp ;

PAIR P[2000] ;
int ans = 0 , Sum[200001];

void calc(){
	Arr[0] = 1 ;
	inv[0] = inv[1] = 1;
	for ( int i = 1 ; i < (200001 << 1) ; i++ ){
		Arr[i] = (Arr[i-1] *1LL* i ) % mod ;
		if(i > 1){
			inv[i] = (- (mod / i) *1LL* inv[mod %i])%mod;
			inv[i] = (inv[i]%mod + mod)%mod;
		}
	}
}

int main(){
	calc();
	int n , m , x ;
	scanf("%d %d %d",&n,&m,&x);
	for ( int i = 0 ; i < x ; i++ ) scanf("%d %d",&P[i].first,&P[i].second);
	sort(P,P+x,&cmp);
	for ( int i = 0 ; i < x ; i++ ){
		A = P[i].first , B = P[i].second ;
		Get(Sum[i]);
		for ( int j = 0; j < i ; j++ )
			if (P[j].first <= P[i].first && P[j].second <= P[i].second){
				A = P[i].first-P[j].first+1;
				B = P[i].second-P[j].second+1;
				Get(tmp);
				Sum[i] = (Sum[i] - tmp*1LL*Sum[j])%mod;
				Sum[i] = (Sum[i] + mod) % mod ;
			}
		A = n-P[i].first+1 , B = m-P[i].second+1 ;
		Get(tmp);
		ans = (ans + Sum[i]*1LL*tmp)%mod;
	}
	A = n , B = m ; Get(tmp);
	ans = ((tmp - ans)%mod + mod)%mod;
	printf("%d\n",ans);
	return 0;
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>
#include <unordered_map>
#define Get() (Arr[A+B-2LL]*1LL*inv[A - 1LL]%mod * 1LL * inv[B - 1LL]%mod)
#define gc getchar
using namespace std;

struct PAIR{
	int first,second;
};

bool cmp(const PAIR & p1,const PAIR & p2){
	return (p1.first == p2.first) ? p1.second < p2.second : p1.first < p2.first;
}

int Arr[200001] , PP ;
int Pow( int a )
{
	int b = a,c = 1;
	while(PP > 1){
		if(PP & 1) c = (c *1LL* b)%mod;
		b = (b *1LL* b)%mod;
		PP >>= 1;
	}
	return (b *1LL* c)%mod;
}

int A ,B , tmp ;

PAIR P[2000] ;
int ans = 0 , Sum[200001],inv[200001];

void calc(){
	Arr[0] = 1 ;
	inv[0] = 1 ;
	for ( int i = 1 ; i < 200001 ; i++ ){
		Arr[i] = (Arr[i-1] *1LL* i ) % mod ;
		PP = mod - 2;
		inv[i] = Pow(Arr[i]);
	}
}

int main(){
	calc();
	int n , m , x ;
	scanf("%d %d %d",&n,&m,&x);
	for ( int i = 0 ; i < x ; i++ )
		scanf("%d %d",&P[i].first,&P[i].second);
	sort(P,P+x,&cmp);
	for ( int i = 0 ; i < x ; i++ ){
		A = P[i].first , B = P[i].second ;
		Sum[i] = Get();
		for ( int j = 0; j < i ; j++ )
			if (P[j].first <= P[i].first && P[j].second <= P[i].second){
				A = P[i].first-P[j].first+1;
				B = P[i].second-P[j].second+1;
				tmp = Get();
				Sum[i] = (Sum[i] - tmp*1LL*Sum[j])%mod;
				Sum[i] = (Sum[i] + mod) % mod ;
			}
		A = n-P[i].first+1 , B = m-P[i].second+1 ;
		tmp = Get();
		ans = (ans + Sum[i]*1LL*tmp)%mod;
	}
	A = n , B = m ; tmp = Get();
	ans = ((tmp - ans)%mod + mod)%mod;
	printf("%d\n",ans);
	return 0;
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>

using namespace std;

long long Arr[200001] , PP ;

long long Pow( long long a )
{
	if(!PP) return 1;
	long long ans = a,b = 1;
	while(PP > 1){
		if(PP & 1) b = (b * ans) % mod;
		ans = (ans * ans)%mod;
		PP >>= 1;
	}
	return (ans * b)%mod;
}

long long A ,B , tmp ;
long long Get()
{
    PP = mod-2 ;
    tmp = (Arr[A+B-2LL]*Pow(Arr[A+B-2LL-(B-1LL)])%mod );
    PP = mod-2 ;
    return tmp* Pow(Arr[B-1])%mod ;
}
void calc()
{
    Arr[0] = 1 ;
    for ( int i = 1 ; i < 200001 ; i++ )
        (Arr[i] = Arr[i-1] * i ) %= mod ;
}
int main()
{
    calc();
    long long n , m , x ;
    scanf("%I64d %I64d %I64d",&n,&m,&x);
    pair < long long , long long > P[x] ;
    for ( int i = 0 ; i < x ; i++ )
        scanf("%I64d %I64d",&P[i].first,&P[i].second);
    long long ans = 0 , Sum[200001] = {} ;
    sort(P,P+x);
    for ( int i = 0 ; i < x ; i++ )
    {
        A = P[i].first , B = P[i].second ;
        Sum[i] = Get();
        for ( int j = 0; j < i ; j++ )
        if ( P[j].first <= P[i].first && P[j].second <= P[i].second )
            A = P[i].first-P[j].first+1, B =P[i].second-P[j].second+1, Sum[i] -= Get()*Sum[j] , Sum[i] %=mod ;
        (Sum[i] += mod) %= mod ;
        A = n-P[i].first+1 , B = m-P[i].second+1 ;
        ans += Sum[i]*Get();
        (ans += mod) %=mod;
    }
    A = n , B = m ;
    printf("%I64d",(Get()-ans+mod)%mod);
    return 0;
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>

using namespace std;

long long Arr[200001] , PP ;

long long Pow( long long a )
{
	if(!PP) return 1;
	long long ans = a,b = 1;
	while(PP > 1){
		if(PP & 1) b = (b * ans) % mod;
		ans = (ans * ans)%mod;
		PP >>= 1;
	}
	return (ans * b)%mod;
}

void scan(long long & x){
	x = 0;
	char c;
	#define gc getchar
	while(!('0' <= (c = gc()) && c <= '9'));
	x = c - '0';
	while('0' <= (c = gc()) && c <= '9') x = (x << 1) + (x << 3) + c - '0';
}

long long A ,B , tmp ;
inline long long Get()
{
    PP = mod-2 ;
    tmp = Arr[A+B-2LL]*Pow(Arr[A+B-2LL-(B-1LL)])%mod;
    PP = mod-2 ;
    return tmp* Pow(Arr[B-1])%mod ;
}
void calc()
{
    Arr[0] = 1 ;
    for ( int i = 1 ; i < 200001 ; i++ )
        (Arr[i] = Arr[i-1] * i ) %= mod ;
}
int main()
{
    calc();
    long long n , m , x ;
    scan(n); scan(m); scan(x);
    pair < long long , long long > P[x] ;
    for ( int i = 0 ; i < x ; i++ )
        scan(P[i].first),scan(P[i].second);
    long long ans = 0 , Sum[200001] = {} ;
    sort(P,P+x);
    for ( int i = 0 ; i < x ; i++ )
    {
        A = P[i].first , B = P[i].second ;
        Sum[i] = Get();
        for ( int j = 0; j < i ; j++ )
        if ( P[j].first <= P[i].first && P[j].second <= P[i].second )
            A = P[i].first-P[j].first+1, B =P[i].second-P[j].second+1, Sum[i] -= Get()*Sum[j] , Sum[i] %=mod ;
        (Sum[i] += mod) %= mod ;
        A = n-P[i].first+1 , B = m-P[i].second+1 ;
        ans += Sum[i]*Get();
        (ans += mod) %=mod;
    }
    A = n , B = m ;
    printf("%I64d",(Get()-ans+mod)%mod);
    return 0;
}


#include <iostream>
#define mod 1000000007
#include <cmath>
#include <algorithm>
#include <stdio.h>

using namespace std;

long long Arr[200001] , PP ;

long long Pow( long long a )
{
	if(!PP) return 1;
	long long ans = a,b = 1;
	while(PP > 1){
		if(PP & 1) (b *= ans) %= mod;
		(ans *= ans)%mod;
		PP >>= 1;
	}
	return (ans * b)%mod;
}
long long A ,B , tmp ;
long long Get()
{
    PP = mod-2 ;
    tmp = (Arr[A+B-2LL]*Pow(Arr[A+B-2LL-(B-1LL)])%mod );
    PP = mod-2 ;
    return tmp* Pow(Arr[B-1])%mod ;
}
void calc()
{
    Arr[0] = 1 ;
    for ( int i = 1 ; i < 200001 ; i++ )
        (Arr[i] = Arr[i-1] * i ) %= mod ;
}
int main()
{
    calc();
    long long n , m , x ;
    scanf("%I64d %I64d %I64d",&n,&m,&x);
    pair < long long , long long > P[x] ;
    for ( int i = 0 ; i < x ; i++ )
        scanf("%I64d %I64d",&P[i].first,&P[i].second);
    long long ans = 0 , Sum[200001] = {} ;
    sort(P,P+x);
    for ( int i = 0 ; i < x ; i++ )
    {
        A = P[i].first , B = P[i].second ;
        Sum[i] = Get();
        for ( int j = 0; j < i ; j++ )
        if ( P[j].first <= P[i].first && P[j].second <= P[i].second )
            A = P[i].first-P[j].first+1, B =P[i].second-P[j].second+1, Sum[i] -= Get()*Sum[j] , Sum[i] %=mod ;
        (Sum[i] += mod) %= mod ;
        A = n-P[i].first+1 , B = m-P[i].second+1 ;
        ans += Sum[i]*Get();
        (ans += mod) %=mod;
    }
    A = n , B = m ;
    printf("%I64d",(Get()-ans+mod)%mod);
    return 0;
}


#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read(){
   int s=0,w=1;char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
   return s*w;
}
const int N=1e5+5;
const int mod=1e9+7;
LL jc[N],inv[N],f[2005];
struct ppx{
    int x,y;
}a[2005];
inline bool cmp(const ppx &a,const ppx &b){return a.x==b.x?a.y<b.y:a.x<b.x;}
inline LL ksm(LL a,int b){
    LL cnt=1;
    while(b){
	if(b&1)cnt=(1ll*cnt*a)%mod;
	a=(1ll*a*a)%mod;
	b>>=1;
    }
    return cnt;
}
inline LL C(int n,int m){return jc[n]*inv[m]%mod*inv[n-m]%mod;}
int main(){
    jc[0]=1;inv[0]=1;
    for(int i=1;i<=100000;++i){
	jc[i]=jc[i-1]*i%mod;
	inv[i]=ksm(jc[i],mod-2);
    }
    int h=read(),w=read(),n=read();
    for(int i=1;i<=n;++i){
	a[i].x=read();a[i].y=read();
    }
    sort(a+1,a+n+1,cmp);
    a[n+1].x=h;a[n+1].y=w;
    for(int i=1;i<=n+1;++i){
	f[i]=C(a[i].x+a[i].y-2,a[i].x-1);
	for(int j=1;j<i;++j)
	    f[i]=(f[i]-1ll*f[j]*C(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x))%mod;
    }
    printf("%lld\n",f[n+1]%mod);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
#include<cmath>
#define ll long long
using namespace std;
int h, w, n, f[SIZE], mod = 1000000007;
long long jc[200010], jcinv[200010];
const int SIZE = 2010;
struct Node
{
	int x,y;
}a[SIZE];
bool operator<(const Node &a,const Node &b){
	return a.x<b.x;
}
int C(int n, int m) {
	return jc[n] * jcinv[m] % mod * jcinv[n - m] % mod;
}

ll ksm(ll x,int y)
{
	ll ans=1;
	while(y)
	{
		if(y%2==1) ans=(ans*x)%mod;
		x=(x*x)%mod;
		y=y/2;
	}
	return ans;
}

int main() {
	jc[0] = 1, jcinv[0] = 1;
	for (int i = 1; i <= 200000; i++) {
		jc[i] = jc[i - 1] * i % mod;
		jcinv[i] = ksm(jc[i], mod - 2);
	}
	cin >> h >> w >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d%d", &a[i].x, &a[i].y);
	sort(a + 1, a + n + 1);
	a[n + 1].x = h, a[n + 1].y = w;
	for (int i = 1; i <= n + 1; i++) {
		f[i] = C(a[i].x + a[i].y - 2, a[i].x - 1);
		for (int j = 1; j < i; j++) {
			if (a[j].x > a[i].x || a[j].y > a[i].y) continue;
			f[i] = (f[i] - (long long)f[j] * C(a[i].x + a[i].y - a[j].x - a[j].y, a[i].x - a[j].x)) % mod;
		}
	}
	cout << (f[n + 1] + mod) % mod << endl;
}


#include <bits/stdc++.h>
using namespace std;
int h,w,n;
long long f[4000],jc[300000],inv[300000],mo;
struct node
{
	int x,y;
}a[5000];
inline bool cmp(node x,node y)
{
	if (x.x!=y.x) return x.x<y.x;
	else return x.y<y.y;
}
inline long long power(long long u,long long b)
{
	long long s=1;
	while (b)
	{
		if (b&1) s=s*u%mo;
		u=u*u%mo;
		b>>=1;
	}
	return s;
}
inline long long c(int u,int v)
{
	return jc[u]*inv[v]%mo*inv[u-v]%mo;
}
int main()
{
	mo=1000000007;
	scanf("%d%d%d",&h,&w,&n);
	jc[0]=0;
	jc[1]=1;
	int sd=200001;
	for (int i=2;i<=sd+1;i++)jc[i]=(jc[i-1]*i)%mo;
	inv[sd+1]=power(jc[sd+1],1LL*(mo-2));
	for (int i=sd;i>=0;i--)inv[i]=inv[i+1]*1LL*(i+1)%mo;
	for (int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
	sort(a+1,a+n+1,cmp);
	n++;
	a[n].x=h;a[n].y=w;
	for (int i=1;i<=n;i++)
	{
		//long long sum=0;
		f[i]=c(a[i].x+a[i].y-2,a[i].x-1)%mo;
		for (int j=1;j<i;j++)
		{
			if (a[j].x>a[i].x||a[j].y>a[i].y) continue;
			f[i]=(f[i]-(long long )f[j]*c(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x))%mo;
			//sum=(sum+f[j]*c(a[i].x-a[j].x+a[i].y-a[j].y,a[i].x-a[j].x)%mo)%mo;
		}
		f[i]=(f[i]+mo)%mo;
		//f[i]-=sum;
	}
	if (f[n]>0)printf("%lld",f[n]);
	else printf("%lld",f[n/2]);
	return 0;
}


#include<bits/stdc++.h>
#define x first
#define y second
#define ll long long
#define prll pair<ll,ll>
using namespace std;
const ll MOD=1000000007;
prll a[2010];
ll h,w,n,f[2010],jc[200010],jcinv[200010];
ll C(ll n,ll m)
{
    return jc[n]*jcinv[m]%MOD*jcinv[n-m]%MOD;
}
ll power(ll a,ll b)
{
    ll c=1;
    for(; b; b>>=1)
    {
        if(b&1) c=c*a%MOD;
        a=a*a%MOD;
    }
    return c;
}
signed main()
{
    jc[0]=1; jcinv[0]=1;
    for(ll i=1; i<=200000; i++)
    {
        jc[i]=jc[i-1]*i%MOD;
        jcinv[i]=power(jc[i],MOD-2);
    }
    cin>>h>>w>>n;
    for(ll i=1; i<=n; i++) scanf("%lld %lld",&a[i].x,&a[i].y);
    sort(a+1,a+1+n);
    a[n+1].x=h; a[n+1].y=w;
    for(ll i=1; i<=n+1; i++)
    {
        f[i]=C(a[i].x+a[i].y-2,a[i].x-1);
        for(ll j=1; j<i; j++)
        {
            if(a[j].x>a[i].x||a[j].y>a[i].y) continue;
            f[i]=(f[i]-f[j]*C(a[i].x+a[i].y-a[j].x-a[j].y,a[i].x-a[j].x))%MOD;
        }
    }
    cout<<(f[n+1]+MOD)%MOD<<endl;
}


#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e5+5;
const int K=2005;
const int Mod=1e9+7;
typedef long long LL;
int n,m,k;
LL f[K],Inv[N<<1],Sum[N<<1];
struct Node{
	int x,y;
}p[N];
inline int Read(){
	char ch;int f=1,x;
	while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;x=ch^48;
	while((ch=getchar())>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline bool Cmp(const Node x,const Node y){
	return x.x<y.x||(x.x==y.x&&x.y<y.y);
}
inline LL MyPow(LL a,int b){
	LL ss=1;
	for(;b;b>>=1){
		if(b&1) ss=ss*a%Mod;
		a=a*a%Mod;
	}
	return ss;
}
inline void Init(){
	n=Read();m=Read();k=Read();
	for(register int i=1;i<=k;i++){
		p[i].x=Read();
		p[i].y=Read();
	}
	p[k+1].x=n;p[k+1].y=m;
	sort(p+1,p+k+1,Cmp);
	Sum[0]=1;Inv[0]=1;
	for(register int i=1;i<=n+m;i++){
		Sum[i]=Sum[i-1]*i%Mod;
		Inv[i]=MyPow(Sum[i],Mod-2);
//		printf("%d\n",Inv[i]);
	}
}
inline LL C(const int m,const int n){
	return Sum[m]*Inv[m-n]%Mod*Inv[n]%Mod;
}
inline void Query(){
	for(register int i=1;i<=k+1;i++){
		f[i]=C(p[i].x+p[i].y-2,p[i].x-1);
//		printf("%lld\n",f[i]);
		for(register int j=1;j<i;j++)
			if(p[j].x<=p[i].x&&p[j].y<=p[i].y){
				f[i]=(f[i]-f[j]*C(p[i].x-p[j].x+p[i].y-p[j].y,p[i].x-p[j].x)%Mod+Mod)%Mod;
			}
	}
	printf("%lld\n",f[k+1]);
}
inline void Debug(){
	int x,y;
	while(1){
		x=Read();
		y=Read();
		printf("%d\n",C(x,y));
	}
//	while(1){
//		x=Read();
//		printf("%d\n",Inv[x]);
//	}
}
int main(){
	Init();
	Query();
//	Debug();
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int N=2020;
const int M=20200;
int f[N];
struct pnt
{
	int xi,yi;
}d[N];
bool operator<(pnt a,pnt b)
{
	return a.yi<b.yi||(a.yi==b.yi&&a.xi<b.xi);
}
int jc[M],jcv[M];
int n,h,w;
int ksm(int x,int k)
{
	int res=1;
	while(k)
	{
		if(k&1) res=1ll*res*x%mod;
		k>>=1;x=1ll*x*x%mod;
	}
	return res;
}
int C(int n,int m)
{
	return 1ll*jc[n]*jcv[m]%mod*jcv[n-m]%mod;
}
int main()
{
	scanf("%d%d%d",&h,&w,&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&d[i].xi,&d[i].yi);
	sort(d+1,d+1+n);
	jc[0]=1;
	for(int i=1;i<M;i++)
	   jc[i]=1ll*jc[i-1]*i%mod;
	for(int i=0;i<M;i++)
	   jcv[i]=ksm(jc[i],mod-2);
	d[++n].xi=h,d[n].yi=w;
	for(int i=1;i<=n;i++)
	{
	    f[i]=C(d[i].xi+d[i].yi-2,d[i].xi-1);
		//printf("%d\n",f[i]);
		for(int j=1;j<i;j++)
		   if(d[j].xi<=d[i].xi&&d[j].yi<=d[i].yi)
		       f[i]-=1ll*C(d[i].xi+d[i].yi-d[j].xi-d[j].yi,d[i].xi-d[j].xi)*f[j]%mod,f[i]=(f[i]+mod)%mod;
		//printf("%d\n",f[i]);
	}
	printf("%d",(f[n]+mod)%mod);
	return 0;
}


#include<bits/stdc++.h>
#define mode 1000000007
#define maxn 200000
using namespace std;
long long inv[200005],mul[200005],dp[3005];
int n,m,k;
struct Bad{
    int x,y;
}p[3005];
bool cmp(Bad a,Bad b){
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
int C(int x,int y){
    return mul[x]%mode*inv[y]%mode*inv[x-y]%mode;
}
int main(){
    cin>>n>>m>>k;

    inv[1]=1;
    inv[0]=1;
    mul[0]=1;
    for(int i=2;i<=maxn;i++){
        inv[i]=(mode-mode/i)*inv[mode%i]%mode;
    }
    for(int i=1;i<=maxn;i++){
        inv[i]*=inv[i-1];
        inv[i]%=mode;
        mul[i]=mul[i-1]*i;
        mul[i]%=mode;
    }

    for(int i=1;i<=k;++i)
        scanf("%d%d",&p[i].x,&p[i].y);
    k++;
    p[k].x=n;
    p[k].y=m;
    sort(p+1,p+k+1,cmp);
    for(int i=1;i<=k;++i){
        dp[i]=C(p[i].x+p[i].y,p[i].x);
        for(int j=1;j<i;++j)
            if(p[j].x<=p[i].x&&p[j].y<=p[i].y)
                dp[i]-=dp[j]*C(p[i].x-p[j].x+p[i].y-p[j].y,p[i].x-p[j].x)%mode;
        dp[i]=(dp[i]%mode+mode)%mode;
    }
    printf("%lld\n",dp[k]);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define ll long long
const int M=1e9+7;
int h,w,n;
int f[10005][10005];
int a[10005][10005];
int main(){
//	freopen("zx.txt","r",stdin);
    cin>>h>>w>>n;
    for(int i=1;i<=n;i++){
    	int x,y;
    	cin>>x>>y;
    	a[x][y]=1;
	}
	for(int i=1;i<=h;i++) f[i][1]=1;
	for(int i=1;i<=w;i++) f[1][i]=1;
	for(int i=2;i<=h;i++){
		for(int j=2;j<=w;j++){
			if(!a[i][j])
				f[i][j]=(f[i-1][j]+f[i][j-1])%M;
		}
	}
	cout<<f[h][w];
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int M=2005,N=2e5+5,mod=1e9+7;
int h,w,n;
struct point {
	int x,y;
	bool friend operator <(point a,point b) {
		return a.x<b.x||a.x==b.x&&a.y<b.y;
	}
} p[M];
typedef long long LL;
LL f[N]= {1,1},t[N]= {1,1},dp[M];
LL fast_pow(int x,int p) {
	LL res=1,tmp=x;
	while(p) {
		if(p&1) (res*=tmp)%=mod;
		(tmp*=tmp)%=mod;
		p>>=1;
	}
	return res;
}
LL C(int x,int y) {
	if(x>y) return 0;
	return f[y]*t[y-x]%mod*t[x]%mod;
}
int main() {
	scanf("%d%d%d",&h,&w,&n);
	for(int i=1; i<=n; i++)
		scanf("%d%d",&p[i].x,&p[i].y);
	++n,p[n].x=h,p[n].y=w;
	sort(p+1,p+1+n);
	for(int i=2; i<=N-5; i++) {
		f[i]=1ll*f[i-1]*i%mod;
		t[i]=fast_pow(f[i],mod-2);
//		cout<<f[i]<<" "<<t[i]<<'\n';
	}
	for(int i=1; i<=n; i++) {
		dp[i]=C(p[i].x-1,p[i].x+p[i].y-2);
		for(int j=1; j<i; j++) {
//			if(p[i].x<p[j].x||p[i].y<p[j].y) continue;
			dp[i]-=1ll*dp[j]*C(p[i].x-p[j].x,p[i].x+p[i].y-p[j].x-p[j].y)%mod;
			dp[i]=(dp[i]+mod)%mod;
		}
	}
	printf("%lld\n",dp[n]);
	return 0;
}


#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef long long ll;
const int MOD=1e9+7;
int h,w,n,ans;
pair<int,int>black[2003];
ll fact[200003];
ll inv[200003];
ll f[2003];
ll qpow(ll a,ll b,ll p){
	ll ans=1;
	while(b){
		if(b&1)ans=ans*a%p;
		a=a*a%p;
		b>>=1;
	}
	return ans;
}
void pre(int n){
	fact[0]=1;
	for(int i=1;i<=n;i++)
		fact[i]=fact[i-1]*i%MOD;
	inv[n]=qpow(fact[n],MOD-2,MOD);
	for(int i=n-1;i>=0;i--)
		inv[i]=inv[i+1]*(i+1)%MOD;
}
int C(int n,int m){
	if(n==m)
		return 1;
	return fact[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int main(){
	scanf("%d%d%d",&h,&w,&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d",&black[i].x,&black[i].y);
	pre(200000);
	black[n+1].x=h,black[n+1].y=w;
	sort(black+1,black+2+n);
	for(int i=1;i<=n+1;i++){
		f[i]=C(black[i].x+black[i].y-2,black[i].x-1);
		for(int j=1;j<i;j++){
			if(black[i].x<black[j].x||black[i].y<black[j].y)
				continue;
			f[i]=(f[i]-(ll)f[j]*C(black[i].y-black[j].y+black[i].x-black[j].x,black[i].x-black[j].x)%MOD)%MOD;
		}
		while(f[i]<0)
			f[i]+=MOD;
	}
	printf("%d",f[n+1]);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL P=1e9+7;
const int M=2e5;
int X[2005],Y[2005],h,w,n;
LL dp[2005],F[M+5],Fi[M+5];
LL C(int n,int m){
	return F[n]*Fi[n-m]%P*Fi[m]%P;
}
LL fast_pow(LL x,int p){
	LL res=1;
	while(p){
		if(p&1)res=res*x%P;
		x=x*x%P;
		p>>=1;
	}
	return res;
}
void pre(){
	F[0]=1;
	for(int i=1;i<=M;++i)
		F[i]=F[i-1]*i%P;
	Fi[M]=fast_pow(F[M],P-2);
	for(int i=M-1;i>=0;--i)
		Fi[i]=Fi[i+1]*(i+1)%P;
}
int main(){
	cin>>h>>w>>n;
	pre();
	for(int i=1;i<=n;++i)
		scanf("%d%d",&X[i],&Y[i]);
	for(int i=1;i<=n;++i){
		dp[i]=C(X[i]+Y[i]-2,X[i]-1);
		for(int j=1;j<=n;++j){
			if(i!=j&&X[i]>=X[j]&&Y[i]>=Y[j])
				dp[i]=((dp[i]-dp[j]*C(X[i]+Y[i]-X[j]-Y[j],X[i]-X[j]))%P+P)%P;
		}
	}
	LL ans=C(h+w-2,h-1);
	for(int i=1;i<=n;++i){
		ans=(ans-dp[i]*C(h+w-X[i]-Y[i],h-X[i]))%P;
		if(ans<0)ans+=P;
	}
	printf("%lld",ans);
	return 0;
}


#include<cstdio>
#define N 100005
#include<algorithm>
using namespace std;
int H,W,n,P=1e9+7;
long long K1[N<<1];
long long K2[N<<1];
long long dp[2005];
struct node
{
	int x,y;
} A[2005];
long long C(int a,int b)
{
	return K1[a]*K2[b]%P*K2[a-b]%P;
}
bool cmp(node a,node b)
{
	if(a.x!=b.x)return a.x<b.x;
	if(a.x==b.x)return a.y<b.y;
}
void preparing()
{
	K1[0]=1,K2[0]=1,K2[1]=1;
	for(int i=1; i<=200000; i++)K1[i]=i*K1[i-1]%P;
	for(int i=2; i<=200000; i++)K2[i]=-P/i*K2[P%i]%P;
	for(int i=1; i<=200000; i++)K2[i]=K2[i]*K2[i-1]%P;
}
int main()
{
	preparing();
	scanf("%d%d%d",&H,&W,&n);
	for(int i=1; i<=n; i++)
	{
		scanf("%d",&A[i].x);
		scanf("%d",&A[i].y);
	}
	A[++n]=(node)
	{
		H,W
	};
	sort(A+1,A+1+n,cmp);
	for(int i=1; i<=n+1; i++)
	{
		dp[i]=C(A[i].x+A[i].y-2,A[i].x-1);
		for(int j=1; j<=i-1; j++)
		{
			int x=A[i].x-A[j].x;
			int y=A[i].y-A[j].y;
			if(x>=0&&y>=0)dp[i]=(dp[i]-dp[j]*C(x+y,x))%P;
		}
	}
	printf("%lld\n",(dp[n]+P)%P);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int maxn=2005,mod=1e9+7,maxT=2e5+7;

int h,w,n;

struct point{
	int x,y;
}p[maxn];

long long f[maxn],inv[maxT],fac[maxT];

bool cmp(point a,point b)
{
	if(a.x!=b.x)return a.x<b.x;
	else return a.y<b.y;
}

long long poww(long long x,int y)
{
	long long ans=1,base=x%mod;
	while(y){
		if(y&1)ans*=base,ans%=mod;
		base*=base,base%=mod;
		y>>=1;
	}
	return ans;
}

void pre()
{
	fac[0]=fac[1]=1;
	inv[0]=1;
	for(int i=2;i<maxT;++i)
		fac[i]=(fac[i-1]*i)%mod;
	inv[maxT-1]=poww(fac[maxT-1],mod-2);
	for(int i=maxT-2;i>=0;--i)
		inv[i]=inv[i+1]*(i+1)%mod;
}

long long c(int n,int m)
{
	return ((fac[n]*inv[m])%mod*inv[n-m])%mod;
}

int main()
{
	scanf("%d %d %d",&h,&w,&n);
	pre();
	for(int i=1;i<=n;++i){
		scanf("%d %d",&p[i].x,&p[i].y);
	}
	p[++n].x=h,p[n].y=w;
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<=n;++i){
		f[i]=c(p[i].x+p[i].y-2,p[i].x-1);
		for(int j=1;j<i;++j){
			if(p[j].y<=p[i].y){
				f[i]-=f[j]*c(p[i].x-p[j].x+p[i].y-p[j].y,p[i].x-p[j].x)%mod;
				f[i]=(f[i]+mod)%mod;
			}
		}
	}
	printf("%lld",f[n]);
}