#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
const int M = 1e5 + 10;
int n, m, a[N], block, rt[M], cnt[M], mx, L, R, fa[N], maxx, lazy, ans[N];
struct node {
  int flag, l, r, x;
} s[N];
void read(int &x) {
  x = 0;
  int f = 1;
  char c = getchar();
  while (c < '0' || c > '9') {
    if (c == '-') f = -1;
    c = getchar();
  }
  while (c >= '0' && c <= '9') {
    x = x * 10 + c - '0';
    c = getchar();
  }
  x *= f;
}
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
void build(int l, int r) {
  for (int i = l; i <= r; i++) {
    maxx = max(maxx, a[i]);
    if (rt[a[i]])
      fa[i] = rt[a[i]];
    else
      rt[a[i]] = i, fa[i] = i;
    cnt[a[i]]++;
  }
}
void merge(int x, int y) {
  cnt[y] += cnt[x], cnt[x] = 0;
  if (rt[y])
    fa[rt[x]] = rt[y];
  else
    a[rt[x]] = y, rt[y] = rt[x];
  rt[x] = 0;
}
void change(const int &l, const int &r, const int &x) {
  if (maxx - lazy <= x) return;
  if (x * 2 > maxx - lazy) {
    for (int i = maxx; i > x + lazy; i--)
      if (cnt[i]) merge(i, i - x);
    for (int i = x; i >= 1; i--)
      if (cnt[i]) {
        maxx = i;
        break;
      }
  } else {
    for (int i = 1; i <= x; i++) merge(i, i + x);
    lazy += x;
  }
}
void clear(int l, int r) {
  maxx = lazy = 0;
  for (int i = l; i <= r; i++) {
    a[i] = a[find(i)];
    cnt[a[i]] = rt[a[i]] = 0;
  }
}
void rebuild(int l, int r, int x) {
  for (int i = l; i <= r; i++) {
    a[i] = a[find(i)];
    cnt[a[i]] = rt[a[i]] = 0;
    if (fa[i] == i) a[i] -= lazy;
  }
  L = max(l, L), R = min(r, R);
  maxx = 0;
  lazy = 0;
  for (int i = L; i <= R; i++) a[i] = a[i] > x ? a[i] - x : a[i];
  build(l, r);
}
void ask(int l, int r, int x, int id) {
  L = max(l, L), R = min(r, R);
  for (int i = L; i <= R; i++) ans[id] += (a[find(i)] - lazy == x);
}
void solve(const int &l, const int &r) {
  build(l, r);
  for (int i = 1; i <= m; ++i)
    if (s[i].flag ^ 2) {
      L = s[i].l, R = s[i].r;
      if (l >= s[i].l && r <= s[i].r)
        change(l, r, s[i].x);
      else
        rebuild(l, r, s[i].x);
    } else {
      L = s[i].l, R = s[i].r;
      if (l > R || r < L) continue;
      if (l >= s[i].l && r <= s[i].r)
        ans[i] += cnt[s[i].x + lazy];
      else
        ask(l, r, s[i].x, i);
    }
  clear(l, r);
}
int main() {
  read(n), read(m);
  for (int i = 1; i <= n; i++) read(a[i]);
  for (int i = 1; i <= m; i++)
    read(s[i].flag), read(s[i].l), read(s[i].r), read(s[i].x);
  block = sqrt(n);
  int l = 1;
  for (int i = 2; i <= n; i++)
    if ((i - 2) / block != (i - 1) / block) solve(l, i - 1), l = i;
  solve(l, n);
  for (int i = 1; i <= m; i++)
    if (s[i].flag ^ 1) printf("%d\n", ans[i]);
  return 0;
}
