#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long x = 0, f = 1;
  char ch = getchar();
  while (ch > '9' || ch < '0') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
const long long N = 1e5 + 5, SZ = 320;
long long fa[N], val[N];
struct DSU {
  long long sz[N], rt[N];
  inline long long getfa(long long x) {
    if (fa[x] == x) return x;
    return fa[x] = getfa(fa[x]);
  }
  inline void merge(long long p, long long x, long long y) {
    if (rt[y])
      fa[rt[x] + (p - 1) * SZ] = rt[y] + (p - 1) * SZ;
    else {
      rt[y] = rt[x];
      val[rt[y] + (p - 1) * SZ] = y;
    }
    sz[y] += sz[x];
    rt[x] = sz[x] = 0;
  }
} D[SZ + 5];
long long n, m;
long long a[N];
long long pos[N];
long long Max[N];
long long tag[N];
inline void Break(long long P) {
  for (long long 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].rt[a[j]] = 0;
    a[j] -= tag[P];
  }
  for (long long j = (P - 1) * SZ + 1; j <= min(P * SZ, n); j++) fa[j] = 0;
  tag[P] = 0;
}
inline void Build(long long P) {
  Max[P] = 0;
  for (long long i = (P - 1) * SZ + 1; i <= P * SZ; i++) {
    Max[P] = max(Max[P], a[i]);
    if (D[P].rt[a[i]] == 0) {
      fa[i] = i;
      D[P].rt[a[i]] = i - (P - 1) * SZ;
      val[i] = a[i];
    } else
      fa[i] = D[P].rt[a[i]] + (P - 1) * SZ;
    D[P].sz[a[i]]++;
  }
}
inline void update(long long P, long long l, long long r, long long x) {
  Break(P);
  for (long long i = l; i <= r; i++)
    if (a[i] > x) a[i] -= x;
  Build(P);
}
inline void UPDATE(long long P, long long x) {
  if (Max[P] - tag[P] >= x * 2) {
    for (long long i = tag[P] + 1; i <= tag[P] + x; i++)
      if (D[P].rt[i]) D[P].merge(P, i, i + x);
    tag[P] += x;
  } else {
    for (long long i = Max[P]; i > tag[P] + x; i--)
      if (D[P].rt[i]) D[P].merge(P, i, i - x);
    Max[P] = min(tag[P] + x, Max[P]);
  }
}
inline long long query(long long P, long long l, long long r, long long x) {
  long long ans = 0;
  for (long long i = l; i <= r; i++)
    if (val[D[P].getfa(i)] - tag[P] == x) ans++;
  return ans;
}
inline long long QUERY(long long P, long long x) {
  if (x + tag[P] > 1e5) return 0;
  return D[P].sz[x + tag[P]];
}
signed main() {
  n = read();
  m = read();
  for (long long i = 1; i <= n; i++) a[i] = read();
  for (long long i = 1; i <= n; i++) pos[i] = (i - 1) / SZ + 1;
  for (long long i = 1; i <= pos[n]; i++) Build(i);
  while (m--) {
    long long opt, l, r, x;
    opt = read();
    l = read();
    r = read();
    x = read();
    if (opt == 1) {
      long long 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 (long long i = Pl + 1; i <= Pr - 1; i++) UPDATE(i, x);
      }
    } else {
      long long Pl = pos[l], Pr = pos[r];
      if (Pl == Pr)
        printf("%lld\n", query(Pl, l, r, x));
      else {
        long long ans = query(Pl, l, Pl * SZ, x);
        ans += query(Pr, (Pr - 1) * SZ + 1, r, x);
        for (long long i = Pl + 1; i <= Pr - 1; i++) ans += QUERY(i, x);
        printf("%lld\n", ans);
      }
    }
  }
}
