#include <bits/stdc++.h>

using namespace std;

typedef long long i64;
typedef i64 int_t;
typedef vector<int_t> vi;
typedef vector<vi> vvi;

typedef pair<int_t, int_t> pi;

#define tr(c, i) for(auto i = (c).begin(); i != (c).end(); i++)
#define pb push_back
#define sz(a) i64((a).size())
#define all(c) (c).begin(), (c).end()
#define REP(s, e, i) for(i=(s); i < (e); ++i)

struct SegTree {
  ///
  using value_type = long long;
  using index_type = vector<value_type>::size_type;
  static const value_type merge(const value_type &v1, const value_type &v2) {
    return min(v1, v2);
  }
  static const value_type update_elem(const value_type &current_value, const value_type &updated_value) {
    return min(current_value, updated_value);
  }
  static const value_type update_lazy(const value_type &lazy_cur, const value_type &lazy_up) {
    return min(lazy_cur, lazy_up);
  }
  static const value_type apply_lazy(const value_type &value, const value_type &lazy, i64 nl, i64 nr) {
    return min(value, lazy);
  }
  const value_type default_value = (1LL << 31) - 1;
  
  ///

  vector<value_type> data, lazy;
  index_type n;
  
  SegTree(i64 n_) {
    i64 s = 1;
    while(s < n_) {
      s *= 2;
    }
    n = s;
    data.resize(s * 2 - 1, default_value);
    lazy.resize(s * 2 - 1, default_value);
  }

  value_type query(index_type l, index_type r, index_type nid, index_type nl, index_type nr) {
    lazy_eval(nid, nl, nr);
    if(nr <= l || r <= nl) {
      return default_value;
    }
    
    if(l <= nl && nr <= r) {
      return data[nid];
    }
    else {
      value_type vl = query(l, r, nid*2+1, nl, (nl+nr)/2);
      value_type vr = query(l, r, nid*2+2, (nl+nr)/2, nr);
      return merge(vl, vr);
    }
  }  
  value_type query(index_type l, index_type r) {
    return query(l, r, 0, 0, n);
  }

  void update(index_type i, value_type x) {
    i += n-1;
    data[i] = update_elem(data[i], x);
    while(i > 0) {
      i = (i - 1) / 2;
      data[i] = merge(data[i*2+1], data[i*2+2]);
    }
  }

  void lazy_eval(index_type nid, index_type nl, index_type nr) {
    if(lazy[nid] != default_value) {
      data[nid] = apply_lazy(data[nid], lazy[nid], nl, nr);
      if(nr - nl > 1) {
	lazy[nid*2+1] = update_lazy(lazy[nid*2+1], lazy[nid]);
	lazy[nid*2+2] = update_lazy(lazy[nid*2+2], lazy[nid]);
      }
      lazy[nid] = default_value;
      //cout << "lazy " << nid << " " << data[nid] << " " << lazy[nid] << " " <<
      // nl << " " << nr << endl;
    }
  }
  
  void range_update(index_type l, index_type r, value_type x, index_type nid, index_type nl, index_type nr) {    
    lazy_eval(nid, nl, nr);    
    if(nr <= l || r <= nl) {
      return;
    } 

    //cout << nid << " " << nl << " " << nr << endl;
    if(l <= nl && nr <= r) {      
      lazy[nid] = x;
      lazy_eval(nid, nl, nr);
    }
    else {
      range_update(l, r, x, nid*2+1, nl, (nl+nr)/2);
      range_update(l, r, x, nid*2+2, (nl+nr)/2, nr);
      data[nid] = merge(data[nid*2+1], data[nid*2+2]);
    }
  }
  
  void range_update(index_type l, index_type r, value_type x) {
    range_update(l, r, x, 0, 0, n);
  }
};


int main(int argc, char *argv[]) {

  i64 N, Q, i;
  cin >> N >> Q;
  i64 B = (N-2) * (N-2);

  N -= 2;
  SegTree tree1(N), tree2(N);
  tree1.range_update(0, N, N);
  tree2.range_update(0, N, N);
  
  REP(0, Q, i) {
    i64 q, x;
    cin >> q >> x;
    x -= 2;
    if(q == 1) {
      i64 val = tree1.query(x, x+1);
      B -= val;
      tree2.range_update(0, val, x);
    }
    else {
      i64 val = tree2.query(x, x+1);
      B -= val;
      tree1.range_update(0, val, x);
    }

    /*
    i64 j;
    cout << "tree1 ";
    REP(0, N, j) {
      cout << tree1.query(j, j+1) << " ";
    }
    cout << endl;
    cout << "tree2 ";
    REP(0, N, j) {
      cout << tree2.query(j, j+1) << " ";
    }
    cout << endl;
    cout << endl;
    */
    
  }

  cout << B << endl;

  return 0;
}


Measured memory_bytes: 19632