#include <bits/stdc++.h>
using namespace std;
void desperate_optimization(int precision) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cout.setf(ios::fixed);
  cout.setf(ios::showpoint);
  cout.precision(precision);
}
const int N = 300000;
deque<int> deq[N + 5];
int arr[N + 5];
int ST[4 * N + 5];
int lazy[4 * N + 5];
void pushdown(int idx, int l, int r) {
  if (lazy[idx] == -1) return;
  if (l != r) {
    lazy[2 * idx + 1] = lazy[idx];
    lazy[2 * idx] = lazy[idx];
  }
  ST[idx] = lazy[idx] * (r - l + 1);
  lazy[idx] = -1;
}
void update(int idx, int l, int r, int le, int ri, int v) {
  pushdown(idx, l, r);
  if (r < le || ri < l) return;
  if (le <= l && r <= ri) {
    lazy[idx] = v;
    pushdown(idx, l, r);
    return;
  }
  int mid = (l + r) / 2;
  update(2 * idx, l, mid, le, ri, v);
  update(2 * idx + 1, mid + 1, r, le, ri, v);
  ST[idx] = ST[2 * idx] + ST[2 * idx + 1];
}
void solve(int tc) {
  int n, m;
  cin >> n >> m;
  int k = 0;
  memset(lazy, -1, sizeof lazy);
  for (int i = 1; i <= m; i++) {
    int stats;
    cin >> stats;
    if (stats == 1) {
      k++;
      int x;
      cin >> x;
      deq[x].push_back(k);
      update(1, 1, m, k, k, 1);
    } else if (stats == 2) {
      int x;
      cin >> x;
      while (!deq[x].empty()) {
        int pos = deq[x].front();
        deq[x].pop_front();
        update(1, 1, m, pos, pos, 0);
      }
    } else {
      int t;
      cin >> t;
      update(1, 1, m, 1, t, 0);
    }
    cout << ST[1] << '\n';
  }
}
int main() {
  desperate_optimization(10);
  int ntc = 1;
  for (int tc = 1; tc <= ntc; tc++) solve(tc);
  return 0;
}
