#include <bits/stdc++.h>
using namespace std;
inline int read() {
  int s = 0, t = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') t = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9')
    s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();
  return s * t;
}
const int N = 1e6 + 5;
const int S = 1000;
int n, m, Maxn, D;
int a[N], b[N], L[N], R[N];
int rt[N], sz[N], f[N], w[N], Ans[N];
int Get(int x) { return f[x] == x ? x : f[x] = Get(f[x]); }
void Merge(int x, int y) {
  if (rt[y])
    f[rt[x]] = rt[y];
  else
    rt[y] = rt[x], w[rt[y]] = y;
  sz[y] += sz[x], rt[x] = sz[x] = 0;
}
struct Node {
  int op, l, r, x;
} q[N];
void Build(int k) {
  Maxn = D = 0;
  for (int i = L[k]; i <= R[k]; i++) {
    Maxn = max(Maxn, a[i]);
    if (rt[a[i]])
      f[i] = rt[a[i]];
    else
      rt[a[i]] = f[i] = i, w[i] = a[i];
    sz[a[i]]++;
  }
}
void Update(int x) {
  if (Maxn <= x * 2) {
    for (int i = x + 1 + D; i <= Maxn + D; i++)
      if (rt[i]) Merge(i, i - x);
    Maxn = min(Maxn, x);
  } else {
    for (int i = 1 + D; i <= x + D; i++)
      if (rt[i]) Merge(i, i + x);
    D += x, Maxn -= x;
  }
}
void Rebuild(int k, int l, int r, int x) {
  for (int i = L[k]; i <= R[k]; i++) {
    a[i] = w[Get(i)];
    rt[a[i]] = sz[a[i]] = 0, a[i] -= D;
  }
  for (int i = L[k]; i <= R[k]; i++) w[i] = 0;
  for (int i = l; i <= r; i++)
    if (a[i] > x) a[i] -= x;
  Build(k);
}
int Query(int k, int l, int r, int x) {
  if (x + D > 5e5) return 0;
  if (l <= L[k] && R[k] <= r)
    return sz[x + D];
  else {
    int res = 0;
    for (int i = max(l, L[k]); i <= min(r, R[k]); i++)
      if (w[Get(i)] - D == x) res++;
    return res;
  }
}
int main() {
  n = read(), m = read();
  for (int i = 1; i <= n; i++) {
    a[i] = read(), b[i] = (i - 1) / S + 1;
    !L[b[i]] ? L[b[i]] = i : 0, R[b[i]] = i;
  }
  for (int i = 1; i <= m; i++) q[i] = (Node){read(), read(), read(), read()};
  for (int k = 1; k <= b[n]; k++) {
    Build(k);
    for (int i = 1; i <= m; i++) {
      int op = q[i].op, l = q[i].l, r = q[i].r, x = q[i].x;
      if (r < L[k] || l > R[k]) continue;
      if (op == 1) {
        if (l <= L[k] && R[k] <= r)
          Update(x);
        else
          Rebuild(k, max(l, L[k]), min(r, R[k]), x);
      }
      if (op == 2) Ans[i] += Query(k, l, r, x);
    }
  }
  for (int i = 1; i <= m; i++)
    if (q[i].op == 2) cout << Ans[i] << '\n';
  return 0;
}
