#include <bits/stdc++.h>
inline int read() {
  static char ch;
  while (ch = getchar(), ch < '0' || ch > '9')
    ;
  int res = ch - 48;
  while (ch = getchar(), ch >= '0' && ch <= '9') res = res * 10 + ch - 48;
  return res;
}
inline unsigned int Rand() {
  static unsigned int x = 998666131;
  return x += x << 2 | 1;
}
const int N = 5001, M = 1e5 + 5, T = 2e6;
int n, m, Q, ans[M];
bool vis[M];
struct QueryT {
  int op, x, y, dir, len, lab;
  inline void Reset1(const int &_op, const int &_dir, const int &_x,
                     const int &_y, const int &_len) {
    op = _op;
    dir = _dir;
    x = _x;
    y = _y;
    len = _len;
  }
  inline void Reset2(const int &_op, const int &_dir, const int &_x,
                     const int &_y, const int &_lab) {
    op = _op;
    dir = _dir;
    x = _x;
    y = _y;
    lab = _lab;
    len = x + y;
  }
  inline bool operator<=(const QueryT &rhs) {
    if (x != rhs.x) return x < rhs.x;
    return op <= rhs.op;
  }
} qry[M * 4], tmp[M * 4];
struct node {
  node *lc, *rc;
  int val, sze;
  unsigned int pri;
  inline void Update() { sze = (lc ? lc->sze : 0) + (rc ? rc->sze : 0) + 1; }
} used[T], *pool = used, *unused[T], **top = unused;
node *rt[5][N];
inline node *new_node() {
  node *res;
  if (top != unused)
    res = *--top;
  else
    res = pool++;
  res->lc = res->rc = NULL;
  return res;
}
inline void del_node(node *&u) {
  if (!u) return;
  del_node(u->lc);
  del_node(u->rc);
  *top++ = u;
  u = NULL;
}
inline void Zig(node *&u) {
  node *v = u->lc;
  u->lc = v->rc;
  v->rc = u;
  v->sze = u->sze;
  u->Update();
  u = v;
}
inline void Zag(node *&u) {
  node *v = u->rc;
  u->rc = v->lc;
  v->lc = u;
  v->sze = u->sze;
  u->Update();
  u = v;
}
inline void Insert(node *&u, const int &val) {
  if (!u) {
    u = new_node();
    u->val = val;
    u->sze = 1;
    u->pri = Rand();
    return;
  }
  ++u->sze;
  if (val <= u->val) {
    Insert(u->lc, val);
    if (u->lc->pri < u->pri) Zig(u);
  } else {
    Insert(u->rc, val);
    if (u->rc->pri < u->pri) Zag(u);
  }
}
inline int moreQuery(node *u, const int &val) {
  if (!u) return 0;
  if (u->val < val) return moreQuery(u->rc, val);
  return (u->rc ? u->rc->sze + 1 : 1) + moreQuery(u->lc, val);
}
inline void add(node **R, int x, const int &val) {
  for (; x <= n; x += x & -x) Insert(R[x], val);
}
inline int Query(node **R, int x, const int &val) {
  int res = 0;
  for (; x > 0; x -= x & -x) res += moreQuery(R[x], val);
  return res;
}
inline void Clear(node **R, int x) {
  for (; x <= n && R[x]; x += x & -x) R[x] = NULL;
}
inline void cdqSolve(const int &l, const int &r) {
  if (l == r) return;
  int mid = l + r >> 1;
  cdqSolve(l, mid);
  cdqSolve(mid + 1, r);
  int ql = l, qr = mid + 1;
  for (int i = (l); i <= (r); ++i) {
    if (qr > r || (ql <= mid && qry[ql] <= qry[qr])) {
      tmp[i] = qry[ql++];
      if (tmp[i].op == 1) add(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
    } else {
      tmp[i] = qry[qr++];
      if (tmp[i].op == 2)
        ans[tmp[i].lab] += Query(rt[tmp[i].dir], tmp[i].y, tmp[i].len);
    }
  }
  for (int i = (l); i <= (r); ++i) {
    qry[i] = tmp[i];
    if (qry[i].op == 1) Clear(rt[qry[i].dir], qry[i].y);
  }
  pool = used;
}
int main() {
  n = read();
  Q = read();
  int op, x, y, len, dir;
  for (int i = (1); i <= (Q); ++i) {
    op = read();
    if (op == 1) {
      dir = read(), x = read(), y = read(), len = read();
      if (dir == 2) y = n - y + 1;
      if (dir == 3) x = n - x + 1;
      if (dir == 4) x = n - x + 1, y = n - y + 1;
      len += x + y;
      qry[++m].Reset1(op, dir, x, y, len);
    } else {
      x = read(), y = read();
      qry[++m].Reset2(op, 1, x, y, i);
      qry[++m].Reset2(op, 2, x, n - y + 1, i);
      qry[++m].Reset2(op, 3, n - x + 1, y, i);
      qry[++m].Reset2(op, 4, n - x + 1, n - y + 1, i);
      vis[i] = true;
    }
  }
  cdqSolve(1, m);
  for (int i = (1); i <= (Q); ++i)
    if (vis[i]) printf("%d\n", ans[i]);
  return 0;
}
