#include <bits/stdc++.h>
namespace in {
char buf[1 << 21], *p1 = buf, *p2 = buf;
inline int getc() {
  return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2)
             ? EOF
             : *p1++;
}
template <typename T>
inline void read(T& t) {
  t = 0;
  int f = 0;
  char ch = getc();
  while (!isdigit(ch)) {
    if (ch == '-') f = 1;
    ch = getc();
  }
  while (isdigit(ch)) {
    t = t * 10 + ch - 48;
    ch = getc();
  }
  if (f) t = -t;
}
template <typename T, typename... Args>
inline void read(T& t, Args&... args) {
  read(t);
  read(args...);
}
}  // namespace in
using namespace std;
const int N = 1e5 + 100, SZ = 320;
int fa[N], val[N];
struct DSU {
  int sz[N], id[N];
  inline int getfa(int x) {
    if (fa[x] == x) return x;
    return fa[x] = getfa(fa[x]);
  }
  inline void merge(int p, int x, int y) {
    if (id[y])
      fa[id[x] + (p - 1) * SZ] = id[y] + (p - 1) * SZ;
    else {
      id[y] = id[x];
      val[id[y] + (p - 1) * SZ] = y;
    }
    sz[y] += sz[x];
    id[x] = sz[x] = 0;
  }
} D[SZ + 5];
int n, m;
int a[N];
int pos[N];
int Max[N];
int tag[N];
inline void Break(int P) {
  for (int j = (P - 1) * SZ + 1; j <= min(P * SZ, n); j++) {
    a[j] = val[D[P].getfa(j)];
    D[P].sz[a[j]] = D[P].id[a[j]] = 0;
    a[j] -= tag[P];
  }
  for (int j = (P - 1) * SZ + 1; j <= min(P * SZ, n); j++) fa[j] = 0;
  tag[P] = 0;
}
inline void Build(int P) {
  Max[P] = 0;
  for (int i = (P - 1) * SZ + 1; i <= P * SZ; i++) {
    Max[P] = max(Max[P], a[i]);
    if (D[P].id[a[i]] == 0) {
      fa[i] = i;
      D[P].id[a[i]] = i - (P - 1) * SZ;
      val[i] = a[i];
    } else
      fa[i] = D[P].id[a[i]] + (P - 1) * SZ;
    D[P].sz[a[i]]++;
  }
}
inline void update(int P, int l, int r, int x) {
  Break(P);
  for (int i = l; i <= r; i++)
    if (a[i] > x) a[i] -= x;
  Build(P);
}
inline void UPDATE(int P, int x) {
  if (Max[P] - tag[P] >= x * 2) {
    for (int i = tag[P] + 1; i <= tag[P] + x; i++)
      if (D[P].id[i]) D[P].merge(P, i, i + x);
    tag[P] += x;
  } else {
    for (int i = Max[P]; i > tag[P] + x; i--)
      if (D[P].id[i]) D[P].merge(P, i, i - x);
    Max[P] = min(tag[P] + x, Max[P]);
  }
}
inline int query(int P, int l, int r, int x) {
  int ans = 0;
  for (int i = l; i <= r; i++)
    if (val[D[P].getfa(i)] - tag[P] == x) ans++;
  return ans;
}
inline int QUERY(int P, int x) {
  if (x + tag[P] > 1e5 + 1) return 0;
  return D[P].sz[x + tag[P]];
}
signed main() {
  in::read(n, m);
  for (int i = 1; i <= n; i++) in::read(a[i]);
  for (int i = 1; i <= n; i++) pos[i] = (i - 1) / SZ + 1;
  for (int i = 1; i <= pos[n]; i++) Build(i);
  while (m--) {
    int opt, l, r, x;
    in::read(opt, l, r, x);
    if (opt == 1) {
      int Pl = pos[l], Pr = pos[r];
      if (Pl == Pr)
        update(Pl, l, r, x);
      else {
        update(Pl, l, Pl * SZ, x);
        update(Pr, (Pr - 1) * SZ + 1, r, x);
        for (int i = Pl + 1; i <= Pr - 1; i++) UPDATE(i, x);
      }
    } else {
      int Pl = pos[l], Pr = pos[r];
      if (Pl == Pr)
        printf("%d\n", query(Pl, l, r, x));
      else {
        int ans = query(Pl, l, Pl * SZ, x);
        ans += query(Pr, (Pr - 1) * SZ + 1, r, x);
        for (int i = Pl + 1; i <= Pr - 1; i++) ans += QUERY(i, x);
        printf("%d\n", ans);
      }
    }
  }
  return 0;
}
