#include <bits/stdc++.h>
using namespace std;
const int OO = 1e9;
const long long INF = 1e18;
const int irand(int lo, int hi) {
  return ((double)rand() / (RAND_MAX + 1.0)) * (hi - lo + 1) + lo;
}
const long long lrand(long long lo, long long hi) {
  return ((double)rand() / (RAND_MAX + 1.0)) * (hi - lo + 1) + lo;
}
template <typename T>
T getnum() {
  int sign = 1;
  T ret = 0;
  char c;
  do {
    c = getchar();
  } while (c == ' ' || c == '\n');
  if (c == '-')
    sign = -1;
  else
    ret = c - '0';
  while (1) {
    c = getchar();
    if (c < '0' || c > '9') break;
    ret = 10 * ret + c - '0';
  }
  return sign * ret;
}
inline void ini(int& x) { x = getnum<int>(); }
inline void scani(int& x) { scanf("%d", &x); }
const int N = 1e5 + 5;
const int BLOCK = 320;
const int NB = N / BLOCK + 1;
int n, m;
int arr[N];
int p[NB][N];
int cnt[NB][N];
int offset[NB], maxval[NB];
int cek(int b, int x) {
  if (p[b][p[b][x]] != p[b][x]) p[b][x] = cek(b, p[b][x]);
  return p[b][x];
}
void build(int b) {
  int s = b * BLOCK;
  maxval[b] = 0;
  offset[b] = 0;
  for (int i = s; i <= min(s + BLOCK - 1, n - 1); i += 1) {
    maxval[b] = max(maxval[b], arr[i]);
  }
  for (int i = 1; i <= maxval[b]; i += 1) {
    cnt[b][i] = 0;
    p[b][i] = i;
  }
  for (int i = s; i <= min(s + BLOCK - 1, n - 1); i += 1) {
    cnt[b][arr[i]]++;
  }
}
void update(int b, int x) {
  if (offset[b] + x >= maxval[b]) return;
  if (x < maxval[b] - offset[b] - x) {
    for (int i = offset[b] + 1; i <= offset[b] + x; i += 1) {
      p[b][i] = i + x;
      cnt[b][i + x] += cnt[b][i];
    }
    offset[b] += x;
  } else {
    for (int i = offset[b] + x + 1; i <= maxval[b]; i += 1) {
      p[b][i] = i - x;
      cnt[b][i - x] += cnt[b][i];
    }
    maxval[b] = offset[b] + x;
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cout.setf(ios::fixed);
  cout.setf(ios::showpoint);
  cout.precision(10);
  cin >> n >> m;
  for (int i = 0; i < n; i++) cin >> arr[i];
  for (int i = 0; i < n; i++) {
    if (i % BLOCK == 0) {
      build(i / BLOCK);
    }
  }
  while (m--) {
    int op, l, r, x;
    cin >> op >> l >> r >> x;
    l--;
    r--;
    if (op == 1) {
      for (int i = l; i <= r; i += 1) {
        if (i % BLOCK == 0 && i + BLOCK - 1 <= r) {
          update(i / BLOCK, x);
          i = i + BLOCK - 1;
        } else {
          arr[i] = cek(i / BLOCK, arr[i]);
          assert(arr[i] > offset[i / BLOCK] && arr[i] <= maxval[i / BLOCK]);
          if (arr[i] > offset[i / BLOCK] + x) {
            cnt[i / BLOCK][arr[i]]--;
            arr[i] -= x;
            cnt[i / BLOCK][arr[i]]++;
          }
        }
      }
    } else {
      int ans = 0;
      for (int i = l; i <= r; i += 1) {
        if (i % BLOCK == 0 && i + BLOCK - 1 <= r) {
          if (offset[i / BLOCK] + x <= maxval[i / BLOCK]) {
            ans += cnt[i / BLOCK][offset[i / BLOCK] + x];
          }
          i = i + BLOCK - 1;
        } else {
          arr[i] = cek(i / BLOCK, arr[i]);
          assert(arr[i] > offset[i / BLOCK] && arr[i] <= maxval[i / BLOCK]);
          if (arr[i] == offset[i / BLOCK] + x) {
            ans++;
          }
        }
      }
      cout << ans << '\n';
    }
  }
  return 0;
}
