Problem:
Score : 600 points

Problem Statement

There is a grid with N rows and N columns of squares. Let (i, j) be the square at the i-th row from the top and the j-th column from the left.

Each of the central (N-2) \times (N-2) squares in the grid has a black stone on it.
Each of the 2N - 1 squares on the bottom side and the right side has a white stone on it.

Q queries are given. We ask you to process them in order.
There are two kinds of queries. Their input format and description are as follows:

1 x: Place a white stone on (1, x). After that, for each black stone between (1, x) and the first white stone you hit if you go down from (1, x), replace it with a white stone.

2 x: Place a white stone on (x, 1). After that, for each black stone between (x, 1) and the first white stone you hit if you go right from (x, 1), replace it with a white stone.

How many black stones are there on the grid after processing all Q queries?

Constraints

3 \leq N \leq 2\times 10^5

0 \leq Q \leq \min(2N-4,2\times 10^5)

2 \leq x \leq N-1

Queries are pairwise distinct.

Input

Input is given from Standard Input in the following format:

N Q
Query_1
\vdots
Query_Q

Output

Print how many black stones there are on the grid after processing all Q queries.

Sample Input 1

5 5
1 3
2 3
1 4
2 2
1 2

Sample Output 1

1

After each query, the grid changes in the following way:

Sample Input 2

200000 0

Sample Output 2

39999200004

Sample Input 3

176527 15
1 81279
2 22308
2 133061
1 80744
2 44603
1 170938
2 139754
2 15220
1 172794
1 159290
2 156968
1 56426
2 77429
1 97459
2 71282

Sample Output 3

31159505795

Solution in Java (OpenJDK 11.0.6) (judge verdict: Accepted)

import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.NoSuchElementException;
import java.util.Objects;
public class Main {
	public static void main(String[] args)throws Exception{
		PrintWriter out = new PrintWriter(System.out);
		int N=nextInt();
		int Q=nextInt();
		int x=N,y=N;
		long ans=(long)(N-2)*(N-2);
		ArrayList<Integer> X=new ArrayList<Integer>();
		ArrayList<Integer> Y=new ArrayList<Integer>();
		int hx[]=new int[N];
		int hy[]=new int[N];
		boolean vx[]=new boolean[N];
		boolean vy[]=new boolean[N];
		X.add(N-1);Y.add(N-1);
		hx[0]=N-1; hx[N-1]=N-1;
		hy[0]=N-1; hy[N-1]=N-1;
		for(int i=0;i<Q;i++){
			int a=nextInt();
			int b=nextInt();
			int c=0;
			if(a==1){
				if(vx[b-1]==false){
					c=binary(b-1,X);
					ans-=hx[X.get(c)]-1;
					if(x>b){
						if(hy[hx[X.get(c)]]==0)
							Y.add(0,hx[X.get(c)]);
						hy[0]=b-1;
						hy[hx[X.get(c)]]=b-1;
						x=b;
					}
					vx[b-1]=true;
				}
			}
			else{
				if(vy[b-1]==false){
					c=binary(b-1,Y);
					if(c<0)
						c=0;
					ans-=hy[Y.get(c)]-1;
					if(y>b){
						if(hx[hy[Y.get(c)]]==0)
							X.add(0,hy[Y.get(c)]);
						hx[0]=b-1;
						hx[hy[Y.get(c)]]=b-1;
						y=b;
					}
					vy[b-1]=true;
				}
			}
		}
		System.out.println(ans);
	}
	public static long lmod(long i, long j) {
	     return (i%j)<0?(i%j)+0+(j<0?-j:j):(i%j+0);
	 }
	static boolean isOK(int index,int key,ArrayList<Integer> a){
		if (a.get(index)>=key) return true;
	    else return false;
	}
	static int binary(int key,ArrayList<Integer> a) {
	    int ng = -1; //「index = 0」が条件を満たすこともあるので、初期値は -1
	    int ok = (int)a.size(); // 「index = a.size()-1」が条件を満たさないこともあるので、初期値は a.size()
	    while (Math.abs(ok - ng) > 1) {
	        int mid = (ok + ng) / 2;
	        if (isOK(mid,key,a)) ok = mid;
	        else ng = mid;
	    }
	    return ok;
	}
	class UnionFind {
	    int Parent[];
	    UnionFind(int n) {// Initialize by -1
	        Parent = new int[n];
	        Arrays.fill(Parent, -1);
	    }
	    int root(int A) {// In which tree is A?
	        if (Parent[A] < 0)
	            return A;
	        return Parent[A] = root(Parent[A]);
	    }
	    int size(int A) {// size of tree which is include A
	        return -Parent[root(A)];
	    }
	    boolean connect(int A, int B) {// Connect A and B
	        A = root(A);
	        B = root(B);
	        if (A == B)
	            return false;
	        if (size(A) < size(B)) {
	            int C = 0;
	            C = B;
	            B = A;
	            A = C;
	        } // SWAP
	        Parent[A] += Parent[B];
	        Parent[B] = A;
	        return true;
	    }
	}
	//FastScanner
	static InputStream in = System.in;
	static  byte[] buffer = new byte[1024];
	static int length = 0, p = 0;
	public static boolean hasNextByte () {
		if (p < length) return true;
		else {
			p = 0;
			try {length = in.read(buffer);}
			catch (Exception e) {e.printStackTrace();}
			if (length == 0) return false;
		}
		return true;
	}
	public static int readByte () {
		if (hasNextByte() == true) return buffer[p++];
		return -1;
	}
	public static boolean isPrintable (int n) {return 33<=n&&n<=126;}
	public static void skip () {
		while (hasNextByte() && !isPrintable(buffer[p])) p++;
	}
	public static boolean hasNext () {skip(); return hasNextByte();}
	public static String next () {
		if (!hasNext()) throw new NoSuchElementException();
		StringBuilder sb = new StringBuilder();
		int temp = readByte();
		while (isPrintable(temp)) {
			sb.appendCodePoint(temp);
			temp = readByte();
		}
		return sb.toString();
	}
	public static int nextInt () {return Math.toIntExact(nextLong());}
	public static int[] nextInts (int n) {
		int[] ar = new int[n];
		for (int i=0; i<n; i++) ar[i] = nextInt();
		return ar;
	}
	public static long nextLong () {
		if (!hasNext()) throw new NoSuchElementException();
		boolean minus = false;
		int temp = readByte();
		if (temp == '-') {
			minus = true;
			temp = readByte();
		}
		if (temp<'0' || '9'<temp) throw new NumberFormatException();
		long n = 0;
		while (isPrintable(temp)) {
			if ('0'<=temp && temp<='9') {
				n *= 10;
				n += temp - '0';
			}
			temp = readByte();
		}
		return minus? -n : n;
	}
}
class Pint {
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Pint) {
            Pint other = (Pint) obj;
            return other.first == this.first && other.second == this.second;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.first, this.second);
    }

    public int first;
    public int second;

    Pint(int x, int y) {
        first = x;
        second = y;
    }

    void set(int x, int y) {
        first = x;
        second = y;
    }
}
class Tpair {
    public int first;
    public int second;
    public long third;

    Tpair(int x, int y, long z) {
        first = x;
        second = y;
        third = z;
    }

    void set(int x, int y, long z) {
        first = x;
        second = y;
        third = z;
    }
}