#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;

#define ff               first
#define ss               second
#define pb               push_back
#define all(x)           (x).begin(), (x).end()
#define mem0(x)          memset(x, 0, sizeof (x))
#define mem1(x)          memset(x, -1, sizeof (x))

typedef long long ll;
typedef vector <int> vi;
typedef vector<vi> vvi;
typedef pair<int, int> ii;
typedef vector <ii> vii;
typedef vector<vii> vvii;
typedef vector <ll> vll;
typedef vector<vll> vvll;
typedef pair<ll, ll> pll;

template<class t> class SegTreeLazy {
    vector<ll> *arr, st, lazy; int n;

    void build(int u, int i, int j) {
        if (i == j) {
            st[u] = (*arr)[i];
            return;
        }
        int m = (i+j)/2, l = u*2+1, r = u*2+2;
        build(l, i, m);
        build(r, m+1, j);
        st[u] = t::merge_op(st[l], st[r]);
    }

    void propagate(int u, int i, int j, ll x) {
        st[u] = t::range_op(st[u], i, j, x);
        if (i != j) {
            lazy[u*2+1] = t::prop_op(lazy[u*2+1], x);
            lazy[u*2+2] = t::prop_op(lazy[u*2+2], x);
        }
        lazy[u] = 0;
    }

    ll query(int a, int b, int u, int i, int j) {
        if (j < a or b < i) return t::neutro;
        if (lazy[u]) propagate(u, i, j, lazy[u]);
        if (a <= i and j <= b) return st[u];
        int m = (i+j)/2, l = u*2+1, r = u*2+2;
        ll x = query(a, b, l, i, m);
        ll y = query(a, b, r, m+1, j);
        return t::merge_op(x, y);
    }

    void update(int a, int b, ll value, int u, int i, int j) {
        if (lazy[u]) propagate(u, i, j, lazy[u]);
        if (a <= i and j <= b) propagate(u, i, j, value);
        else if (j < a or b < i) return;
        else {
            int m = (i+j)/2, l = u*2+1, r = u*2+2;
            update(a, b, value, l, i, m);
            update(a, b, value, r, m+1, j);
            st[u] = t::merge_op(st[l], st[r]);
        }
    }

public:
    SegTreeLazy(vector<ll>& v) {
        arr = &v;
        n = v.size();
        st.resize(n*4+5);
        lazy.assign(n*4+5, 0);
        build(0, 0, n-1);
    }

    ll query(int a, int b) {
        return query(a, b, 0, 0, n-1);
    }

    void update(int a, int b, ll value) {
        update(a, b, value, 0, 0, n-1);
    }
};

struct RMinQ { // range minimum query
    static ll const neutro = LLONG_MAX;
    static ll merge_op(ll x, ll y) { return min(x, y); }
    static ll range_op(ll st_u, int a, int b, ll x) { return st_u + x; }
    static ll prop_op(ll child, ll x) { return child + x; }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll T=1, n;
    while (T--){
        cin >> n;
        vll vertical(n);
        vll horizontal(n);
        for (int i = 0; i < n; ++i) {
            horizontal[i] = vertical[i] = n;
        }
        //horizontal[n-1] = vertical[n-1] = 1;
        SegTreeLazy<RMinQ> hor(horizontal);
        SegTreeLazy<RMinQ> ver(vertical);
        int q; cin >> q;
        ll ans = (n-2)*(n-2);
        for (int j = 0; j < q; ++j) {
            int t, x; cin >> t >> x;
            if (t==1){
                int hasta = hor.query(x-1,x-1);
                ans -= (hasta-2);
                ll qry = ver.query(0, hasta-1);
                if (qry > x) {
                    ver.update(0, hasta - 1, x-qry);
                }
            }else{
                int hasta = ver.query(x-1,x-1);
                ans -= (hasta-2);
                ll qry = hor.query(0, hasta-1);
                if (qry > x)
                    hor.update(0, hasta-1, x - qry);
            }
        }
        cout << ans << "\n";
    }
}

Measured memory_bytes: 31388