#include <bits/stdc++.h>
const int maxn = 100005, maxt = 405;
int i, j, k, m, n, t;
int a[maxn], l[maxt], r[maxt], pos[maxn], f[maxn], val[maxn], maxx[maxt],
    lazy[maxn];
struct DSU {
  int rt[maxn], size[maxn];
  int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
  void merge(int now, int x, int y) {
    if (rt[y])
      f[rt[x] + l[now] - 1] = rt[y] + l[now] - 1;
    else
      rt[y] = rt[x], val[rt[y] + l[now] - 1] = y;
    size[y] += size[x], rt[x] = size[x] = 0;
  }
} dsu[maxt];
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
void reset(int now) {
  maxx[now] = 0;
  for (int i = l[now]; i <= r[now]; i++) {
    maxx[now] = max(maxx[now], a[i]);
    if (dsu[now].rt[a[i]] == 0)
      f[i] = i, dsu[now].rt[a[i]] = i - l[now] + 1, val[i] = a[i];
    else
      f[i] = dsu[now].rt[a[i]] + l[now] - 1;
    dsu[now].size[a[i]]++;
  }
}
void pushdown(int now) {
  for (int i = l[now]; i <= r[now]; i++) {
    a[i] = val[dsu[now].find(i)] - lazy[now];
    dsu[now].size[a[i]] = dsu[now].rt[a[i]] = 0;
  }
  lazy[now] = 0;
  for (int i = l[now]; i <= r[now]; i++) f[i] = 0;
}
void modify(int now, int L, int R, int V) {
  pushdown(now);
  for (int i = L; i <= R; i++)
    if (a[i] > V) a[i] -= V;
  reset(now);
}
void update(int L, int R, int V) {
  int a = pos[L], b = pos[R];
  if (a == b) {
    modify(a, L, R, V);
    return;
  }
  modify(a, L, r[a], V);
  for (int i = a + 1; i <= b - 1; i++) {
    if (maxx[i] - lazy[i] >= V * 2) {
      for (int j = lazy[i] + 1; j <= lazy[i] + V; j++)
        if (dsu[i].rt[j]) dsu[i].merge(i, j, j + V);
      lazy[i] += V;
    } else {
      for (int j = lazy[i] + V + 1; j <= maxx[i]; j++)
        if (dsu[i].rt[j]) dsu[i].merge(i, j, j - V);
      maxx[i] = min(maxx[i], lazy[i] + V);
    }
  }
  modify(b, l[b], R, V);
}
int query(int L, int R, int V) {
  int a = pos[L], b = pos[R], res = 0;
  if (a == b) {
    for (int i = L; i <= R; i++)
      if (val[dsu[a].find(i)] - lazy[a] == V) res++;
    return res;
  }
  for (int i = L; i <= r[a]; i++)
    if (val[dsu[a].find(i)] - lazy[a] == V) res++;
  for (int i = a + 1; i <= b - 1; i++) {
    if (V + lazy[i] >= maxn) continue;
    res += dsu[i].size[V + lazy[i]];
  }
  for (int i = l[b]; i <= R; i++)
    if (val[dsu[b].find(i)] - lazy[b] == V) res++;
  return res;
}
int main() {
  scanf("%d%d", &n, &m);
  t = sqrt(n);
  for (i = 1; i <= t; i++) l[i] = r[i - 1] + 1, r[i] = i * t;
  if (r[t] < n) l[++t] = r[t - 1] + 1, r[t] = n;
  for (i = 1; i <= t; i++)
    for (j = l[i]; j <= r[i]; j++) pos[j] = i;
  for (i = 1; i <= n; i++) scanf("%d", &a[i]);
  for (i = 1; i <= t; i++) reset(i);
  for (i = 1; i <= m; i++) {
    int opt, l, r, x;
    scanf("%d%d%d%d", &opt, &l, &r, &x);
    if (opt == 1) update(l, r, x);
    if (opt == 2) printf("%d\n", query(l, r, x));
  }
  return 0;
}
