#define _CRT_SECURE_NO_WARNINGS

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <cstring>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <list>
#include <random>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <unordered_set>
#include <unordered_map>
#include <array>
#include <cassert>
#include <bitset>
#include <cstdint>
#include <random>
using namespace std;
using LL = long long;

//区間上のすべての要素を変更する処理ができるセグ木(RSQ版)
template<typename T>
class RSQ_modify {
private:
	vector<T> seg;//生データ
	int width;//セグ木の幅(配列の大きさではない！)
	vector<T>lazy;//遅延データ
	vector<bool>flag;//遅延データの有無
	function<T(const T&, const int&)>multi;//積のラムダ式(繰り返し二乗法推奨)

	//k番目のノード[l,r)の遅延伝播をする
	void eval(int k, int l, int r) {
		if (flag[k]) {
			seg[k] = multi(lazy[k], r - l);
			if (r - l > 1) {
				lazy[2 * k + 1] = lazy[k]; flag[2 * k + 1] = true;
				lazy[2 * k + 2] = lazy[k]; flag[2 * k + 2] = true;
			}
			lazy[k] = T();
			flag[k] = false;
		}
	}
	T query_raw(int a, int b, int l, int r, int k) {
		eval(k, l, r);
		if (b <= l || r <= a)return T();
		if (a <= l && r <= b)return seg[k];
		T vl = query_raw(a, b, l, (l + r) / 2, 2 * k + 1);
		T vr = query_raw(a, b, (l + r) / 2, r, 2 * k + 2);
		return vl + vr;
	}
	void update_raw(int a, int b, T x, int l, int r, int k) {
		eval(k, l, r);
		if (b <= l || r <= a)return;
		if (a <= l && r <= b) {
			lazy[k] = x;
			flag[k] = true;
			eval(k, l, r);
		}
		else {
			update_raw(a, b, x, l, (l + r) / 2, 2 * k + 1);
			update_raw(a, b, x, (l + r) / 2, r, 2 * k + 2);
			seg[k] = (seg[2 * k + 1] + seg[2 * k + 2]);
		}
	}
public:
	//サイズn、デフォルト値defのセグ木を作る
	RSQ_modify(int n, function<T(const T&, const int&)>mul)
		: multi(mul) {
		width = 1;
		while (width < n)width *= 2;
		seg.assign(width * 2 - 1, T());
		lazy.assign(seg.size(), T());
		flag.assign(seg.size(), false);
	}
	//区間[a,b)の答えを取得する
	T query(int a, int b) { return query_raw(a, b, 0, width, 0); }
	//区間[a,b)に一様に値xを加算する
	void update(int a, int b, T x) { update_raw(a, b, x, 0, width, 0); }
	//配列ごと初期化する
	void init(const vector<T>& vec) {
		for (int i = 0; i < min(width, (int)vec.size()); i++)
			seg[i + width - 1] = vec[i];
		for (int i = width - 2; i >= 0; i--)
			seg[i] = seg[i * 2 + 1] + seg[i * 2 + 2];
		fill(lazy.begin(), lazy.end(), T());
		fill(flag.begin(), flag.end(), false);
	}
};

LL N, Q;

int main() {
	cin >> N >> Q;
	auto mul = [](const LL& i, const int& j) {return i * j; };
	RSQ_modify<LL> tate(N - 2, mul), yoko(N - 2, mul);
	tate.update(0, N - 2, N - 2);
	yoko.update(0, N - 2, N - 2);
	LL ct = N - 2, cy = N - 2;
	LL ans = (N - 2) * (N - 2);
	for (int i = 0; i < Q; i++) {
		int a, b;
		cin >> a >> b;
		b -= 2;
		if (a == 1) {
			LL val = tate.query(b, b + 1);
			ans -= val;
			if (ct < b) {
			}
			else {
				ct = b;
				yoko.update(0, val, b);
			}
		}
		else {
			LL val = yoko.query(b, b + 1);
			ans -= val;
			if (cy < b) {
			}
			else {
				cy = b;
				tate.update(0, val, b);
			}
		}
		//cout << ans << endl;
	}
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 19896