// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

#define FOR(i,a,b) for(int i=(a);i<(b);++i)

#define REP(i,n) FOR(i,0,n)

#define ALL(v) begin(v),end(v)

#define fi first

#define se second

template<typename A, typename B> inline bool chmax(A &a, B b) { if (a<b) { a=b; return 1; } return 0; }

template<typename A, typename B> inline bool chmin(A &a, B b) { if (a>b) { a=b; return 1; } return 0; }

using ll = long long;

using pii = pair<int, int>;

constexpr ll INF = 1ll<<30;

constexpr ll longINF = 1ll<<60;

constexpr ll MOD = 1000000007;

constexpr bool debug = 0;

//---------------------------------//



#include <vector>

#include <cassert>

#include <functional>



template<typename T, typename E>

struct LazySegmentTree {

	using value_type = T;

	using lazy_type = E;

	using size_type = std::size_t;

	using F = std::function<value_type(const value_type &, const value_type &)>; // 要素の merge

	using G = std::function<value_type(const value_type &, const lazy_type &)>; // 要素に作用素を作用

	using H = std::function<lazy_type(const lazy_type &, const lazy_type &)>; // 作用素の merge

	using P = std::function<lazy_type(const lazy_type &, size_type)>; // 区間への作用がその区間の大きさ(k) に比例して変化するとき p(a, k) := g(a, a, ..., a) (k 個)

	

private:

	size_type n, n_, n_log;

	value_type id_node;

	lazy_type id_lazy;

	F f;

	G g;

	H h;

	P p;

	std::vector<value_type> node;

	std::vector<lazy_type> lazy;



public:

	LazySegmentTree(size_type n, const value_type & id_node, const lazy_type & id_lazy, const F & f, const G & g, const H & h, const P & p = [](const lazy_type & a, size_type l) { return a; })

			: n(n), id_node(id_node), id_lazy(id_lazy), f(f), g(g), h(h), p(p) {

		n_ = 1;

		n_log = 0;

		while (n_ < n) n_ <<= 1, ++n_log;

		node.resize(2 * n_, id_node);

		lazy.resize(2 * n_, id_lazy);

	}

	

	LazySegmentTree(const std::vector<value_type> & v, const value_type & id_node, const lazy_type & id_lazy, const F & f, const G & g, const H & h, const P & p = [](const lazy_type & a, size_type l) { return a; })

			: LazySegmentTree(v.size(), id_node, id_lazy, f, g, h, p) {

		for (size_type i = 0; i < v.size(); ++i) node[i + n_] = v[i];

		for (size_type i = n_ - 1; i > 0; --i) node[i] = f(node[i << 1], node[i << 1 | 1]);

	}

	

	size_type size() const noexcept {

		return n;

	}

	

	void set(size_type k, const value_type & x) {

		assert(k < size());

		k += n_;

		thrust(k);

		node[k] = x;

		lazy[k] = id_lazy;

		recalc(k);

	}

	

	value_type get(size_type k) {

		assert(k < size());

		k += n_;

		thrust(k);

		return reflect(k, 1);

	}

	

	void update(size_type l, size_type r, const lazy_type & x) {

		assert(l <= r);

		assert(r <= size());

		if (l == r) return;

		l += n_;

		r += n_;

		thrust(l);

		thrust(r - 1);

		for(size_type cl = l, cr = r; cl < cr; cl >>= 1, cr >>= 1) {

			if (cl & 1) lazy[cl] = h(lazy[cl], x), ++cl;

			if (cr & 1) --cr, lazy[cr] = h(lazy[cr], x);

		}

		recalc(l);

		recalc(r - 1);

		return;

	}

	

	value_type fold(size_type l, size_type r) {

		assert(l <= r);

		assert(r <= size());

		if (l == r) return id_node;

		l += n_;

		r += n_;

		thrust(l);

		thrust(r - 1);

		value_type vl = id_node, vr = id_node;

		for (size_type w = 1; l < r; l >>= 1, r >>= 1, w <<= 1) {

			if (l & 1) vl = f(vl, reflect(l, w)), ++l;

			if (r & 1) --r, vr = f(reflect(r, w), vr);

		}

		return f(vl, vr);

	}

	

	value_type fold_all() const {

		return node[1];

	}

	

private:

	value_type reflect(size_type k, size_type w) {

		return lazy[k] == id_lazy ? node[k] : g(node[k], p(lazy[k], w));

	}

	

	void propagate(size_type k, size_type w) {

		if (lazy[k] == id_lazy) return;

		if ((k << 1 | 1) < node.size()) {

			lazy[k << 1] = h(lazy[k << 1], lazy[k]);

			lazy[k << 1 | 1] = h(lazy[k << 1 | 1], lazy[k]);

		}

		node[k] = reflect(k, w); // g(node[k], p(lazy[k], l));

		lazy[k] = id_lazy;

	}

	

	void recalc(size_type k) {

		for (size_type i = k >> 1, cw = 1; i > 0; i >>= 1, cw <<= 1)

			node[i] = f(reflect(i << 1, cw), reflect(i << 1 | 1, cw));

	}

	

	void thrust(size_type k) {

		for (size_type i = n_log, w = n_; i > 0; --i, w >>= 1) propagate(k >> i, w);

	}

};



int main() {

	int N, Q;

	cin >> N >> Q;

	

	LazySegmentTree<int, int> col(N, N - 1, INF,

		[](auto && x, auto && y) { return x < y ? x : y; },

		[](auto && x, auto && y) { return y; },

		[](auto && x, auto && y) { return y; });

	auto row = col;

	

	ll black = (ll)(N - 2) * (N - 2);

	int jmin = N, imin = N;

	while (Q--) {

		int q, x;

		scanf("%d %d", &q, &x); --x;

		if (q == 1) {

			// j = x

			int mx = row.get(x);

			black -= mx - 1;

			if (chmin(jmin, x)) col.update(0, mx, x);

		}

		else {

			// i = x

			int mx = col.get(x);

			black -= mx - 1;

			if (chmin(imin, x)) row.update(0, mx, x);

		}

	}

	cout << black << endl;

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.4559346645100004x):
#include <bits/stdc++.h>

using namespace std;

#define FOR(i,a,b) for(int i=(a);i<(b);++i)

#define REP(i,n) FOR(i,0,n)

#define ALL(v) begin(v),end(v)

#define fi first

#define se second

template<typename A, typename B> inline bool chmax(A &a, B b) { if (a<b) { a=b; return 1; } return 0; }

template<typename A, typename B> inline bool chmin(A &a, B b) { if (a>b) { a=b; return 1; } return 0; }

using ll = long long;

using pii = pair<int, int>;

constexpr ll INF = 1ll<<30;

constexpr ll longINF = 1ll<<60;

constexpr ll MOD = 1000000007;

constexpr bool debug = 0;

//---------------------------------//



int main() {

	int N, Q;

	cin >> N >> Q;

	ll black = (ll)(N - 2) * (N - 2);

	

	vector<int> row(N, N - 1), col(N, N - 1);

	int rowmin = N - 1, colmin = N - 1;

	while (Q--) {

		int q, x;

		scanf("%d %d", &q, &x); --x;

		if (q == 1) {

			// col x

			if (colmin > x) {

				FOR(i, x, colmin) col[i] = col[colmin];

				row[col[x]] = x;

				colmin = x;

			}

			black -= col[x] - 1;

		}

		else {

			// row x

			if (rowmin > x) {

				FOR(i, x, rowmin) row[i] = row[rowmin];

				col[row[x]] = x;

				rowmin = x;

			}

			black -= row[x] - 1;

		}

	}

	

	cout << black << endl;

	return 0;

}