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

// DEBUG BEGIN
#ifdef LOCAL
template<typename L, typename R> ostream &operator<<(ostream &out, const pair<L, R> &p){
	return out << "(" << p.first << ", " << p.second << ")";
}
template<typename Tuple, size_t N> struct TuplePrinter{
	static ostream &print(ostream &out, const Tuple &t){ return TuplePrinter<Tuple, N-1>::print(out, t) << ", " << get<N-1>(t); }
};
template<typename Tuple> struct TuplePrinter<Tuple, 1>{
	static ostream &print(ostream &out, const Tuple& t){ return out << get<0>(t); }
};
template<typename... Args> ostream &print_tuple(ostream &out, const tuple<Args...> &t){
	return TuplePrinter<decltype(t), sizeof...(Args)>::print(out << "(", t) << ")";
}
template<typename ...Args> ostream &operator<<(ostream &out, const tuple<Args...> &t){
	return print_tuple(out, t);
}
template<typename T> ostream &operator<<(enable_if_t<!is_same<T, string>::value, ostream> &out, const T &arr){
	out << "{"; for(auto &x: arr) out << x << ", ";
	return out << (arr.size() ? "\b\b" : "") << "}";
}
template<size_t S> ostream &operator<<(ostream &out, const bitset<S> &b){
	for(int i = 0; i < S; ++ i) out << b[i];
	return out;
}
void debug_out(){ cerr << "\b\b " << endl; }
template<typename Head, typename... Tail>
void debug_out(Head H, Tail... T){ cerr << H << ", ", debug_out(T...); }
void debug2_out(){ cerr << "-----DEBUG END-----\n"; }
template<typename Head, typename... Tail>
void debug2_out(Head H, Tail... T){ cerr << "\n"; for(auto x: H) cerr << x << "\n"; debug2_out(T...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: ", debug_out(__VA_ARGS__)
#define debug2(...) cerr << "----DEBUG BEGIN----\n[" << #__VA_ARGS__ << "]:", debug2_out(__VA_ARGS__)
#else
#define debug(...) 42
#define debug2(...) 42
#endif
// DEBUG END

template<typename Q, typename L>
struct lazy_segment_tree{
	lazy_segment_tree(): lazy_segment_tree(0){}
	lazy_segment_tree(int n): lazy_segment_tree(vector<Q>(n)){}
	lazy_segment_tree(const vector<Q> &v): n((int)v.size()){ // O(n)
		log = __lg(n + 1) + 1;
		size = 1 << log;
		val = vector<Q>(size << 1);
		lazy = vector<L>(size);
		copy(v.begin(), v.end(), val.begin() + size);
		for(int i = 1; i < size; ++ i){
			int h = log - __lg(i);
			lazy[i] = {(i << h) - size, (i + 1 << h) - size};
		}
		for(int i = size - 1; i >= 1; -- i) update(i);
	}
	Q query(int p){ // O(log n)
		assert(0 <= p && p < n);
		p += size;
		for(int i = log; i >= 1; -- i) push(p >> i);
		return val[p];
	}
	Q query(int l, int r){ // O(log n)
		assert(0 <= l && l <= r && r <= n);
		if(l == r) return {};
		l += size, r += size;
		for(int i = log; i >= 1; -- i) {
			if(((l >> i) << i) != l) push(l >> i);
			if(((r >> i) << i) != r) push(r >> i);
		}
		Q sml{}, smr{};
		for(; l < r; l >>= 1, r >>= 1){
			if(l & 1) sml = sml + val[l ++];
			if(r & 1) smr = val[-- r] + smr;
		}
		return sml + smr;
	}
	Q query_all(){ return val[1]; } // O(1)
	void update(int p, Q x){ // O(log n)
		assert(0 <= p && p < n);
		p += size;
		for(int i = log; i >= 1; -- i) push(p >> i);
		val[p] = x;
		for(int i = 1; i <= log; ++ i) update(p >> i);
	}
	void update(int p, L f){ // O(log n)
		assert(0 <= p && p < n);
		p += size;
		for(int i = log; i >= 1; -- i) push(p >> i);
		val[p] = f + val[p];
		for(int i = 1; i <= log; ++ i) update(p >> i);
	}
	void update(int l, int r, L f){ // O(log n)
		assert(0 <= l && l <= r && r <= n);
		if(l == r) return;
		l += size, r += size;
		for(int i = log; i >= 1; -- i){
			if(((l >> i) << i) != l) push(l >> i);
			if (((r >> i) << i) != r) push(r - 1 >> i);
		}
		int l2 = l, r2 = r;
		for(; l < r; l >>= 1, r >>= 1){
			if(l & 1) apply(l ++, f);
			if(r & 1) apply(-- r, f);
		}
		l = l2, r = r2;
		for(int i = 1; i <= log; ++ i){
			if(((l >> i) << i) != l) update(l >> i);
			if(((r >> i) << i) != r) update((r - 1) >> i);
		}
	}
	template<typename G> int partition_point_pref(int l, G g){ // O(log n)
		assert(0 <= l && l <= n), assert(g({}));
		if(l == n) return n;
		l += size;
		for(int i = log; i >= 1; ++ i) push(l >> i);
		Q sm{};
		do{
			while(~l & 1) l >>= 1;
			if(!g(sm + val[l])){
				while(l < size){
					push(l);
					l = l << 1;
					if(g(sm + val[l])) sm = sm + val[l ++];
				}
				return l - size;
			}
			sm = sm + val[l];
			++ l;
		}while((l & -l) != l);
		return n;
	} // f(sum[l, r)) is T, T, ..., T, F, F, ..., F, returns max r with T
	template<typename G> int partition_point_suff(int r, G g){ // O(log n)
		assert(0 <= r && r <= n), assert(g({}));
		if(r == 0) return 0;
		r += size;
		for(int i = log; i >= 1; -- i) push(r - 1 >> i);
		Q sm{};
		do{
			-- r;
			while(r > 1 && r & 1) r >>= 1;
			if(!g(val[r] + sm)){
				while(r < size){
					push(r);
					r = r << 1 | 1;
					if(g(val[r] + sm)) sm = val[r --] + sm;
				}
				return r + 1 - size;
			}
			sm = val[r] + sm;
		}while((r & -r) != r);
		return 0;
	} // f(sum[l, r)) is F, F, ..., F, T, T, ..., T, returns min l with T
	int n, size, log;
	vector<Q> val;
	vector<L> lazy;
	void update(int i){ val[i] = val[i << 1] + val[i << 1 | 1]; }
	void apply(int i, L f){
		val[i] = f + val[i];
		if(i < size) lazy[i] = f + lazy[i];
	}
	void push(int i){
		apply(i << 1, lazy[i]), apply(i << 1 | 1, lazy[i]);
		int h = log - __lg(i);
		lazy[i] = {(i << h) - size, (i + 1 << h) - size};
	}
};

struct Q{ // Monoid (Query type) / Default constructor yields the identity
	int val = 0;
	Q operator+(const Q &x) const{
		return {max(val, x.val)};
	} // Monoid operator, always merges adjacent intervals
};
struct L{ // Semigroup (Lazy type) / call L(l, r) for initial lazy type for interval [l, r)
	int val;
	L(){
	}
	L(int val): val(val){
	}
	L(int l, int r): val(-1){
	}
	L operator+(const L &x) const{
		return ~val ? *this : x;
	} // Monoid operator, always applies superset to subset
	Q operator+(const Q &x) const{
		return ~val ? Q{val} : x;
	} // Semigroup action of L on Q, always applies superset to subset
};

int main(){
	cin.tie(0)->sync_with_stdio(0);
	cin.exceptions(ios::badbit | ios::failbit);
	int n, qn;
	cin >> n >> qn;
	int active_v = n - 1, active_h = n - 1;
	vector<Q> v(n - 1, Q{n - 1}), h(n - 1, Q{n - 1});
	lazy_segment_tree<Q, L> segv(v), segh(h);
	long long cnt = 1LL * (n - 2) * (n - 2);
	for(auto qi = 0; qi < qn; ++ qi){
		int type, p;
		cin >> type >> p, -- p;
		if(type == 2){
			swap(active_v, active_h);
			swap(segv, segh);
		}
		int x = segh.query(p).val;
		segh.update(p, Q{0});
		cnt -= x - 1;
		if(p < active_h){
			segv.update(0, x, L{p});
			active_h = p;
		}
		if(type == 2){
			swap(active_v, active_h);
			swap(segv, segh);
		}
	}
	cout << cnt << "\n";
	return 0;
}

/*

*/

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
//                                   Coded by Aeren                                   //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////

Measured memory_bytes: 10856