#include <bits/stdc++.h>
using namespace std;
int N;
int A[100005];
short Root[405][100005], Nb[405][100005];
int Block[100005], M;
int Max[100005], Tag[100005], Left[100005], Right[100005], Pos[100005];
const int limit = 254;
int TT[100005];
void Read() {
  scanf("%d%d", &N, &M);
  for (int i = 1; i <= N; i++) scanf("%d", &A[i]);
}
void precalcBlock() {
  int cnt = 0;
  int bl = 0;
  for (int i = 1; i <= N; i++) {
    ++cnt;
    if (cnt == limit + 1) cnt = 1;
    if (cnt == 1) {
      ++bl;
      Left[bl] = i;
      Right[bl - 1] = i - 1;
    }
    Block[i] = bl;
  }
  Right[bl] = N;
}
int Father(int x) {
  int init = x;
  while (TT[x] != x) {
    x = TT[x];
  }
  while (init != x) {
    int next = TT[init];
    TT[init] = x;
    init = next;
  }
  return x;
}
void Unite(int x, int y) {
  if (x == y) return;
  TT[x] = y;
}
void Merge(int b, int x, int y) {
  int left = Left[b], right = Right[b];
  char nb1 = Nb[b][x];
  char nb2 = Nb[b][y];
  char root1 = Root[b][x];
  char root2 = Root[b][y];
  if (root1 == 0) return;
  if (root2 == 0) {
    Root[b][y] = root1;
    Nb[b][y] = Nb[b][x];
    Pos[root1 + left - 1] = y;
    Nb[b][x] = Root[b][x] = 0;
    return;
  }
  TT[root1 + left - 1] = root2 + left - 1;
  Nb[b][y] += Nb[b][x];
  Nb[b][x] = Root[b][x] = 0;
}
void update(int bl, int x) {
  if (x * 2 <= Max[bl] - Tag[bl]) {
    for (int i = Tag[bl] + 1; i <= Tag[bl] + x; i++) Merge(bl, i, i + x);
    Tag[bl] += x;
  } else {
    for (int i = Max[bl]; i > x + Tag[bl]; i--) Merge(bl, i, i - x);
    Max[bl] = min(Max[bl], Tag[bl] + x);
  }
}
void build(int bl) {
  int left = Left[bl], right = Right[bl];
  Max[bl] = 0;
  int Min = A[left];
  for (int i = left; i <= right; i++) {
    Max[bl] = max(Max[bl], A[i]);
    if (Root[bl][A[i]] == 0) {
      Root[bl][A[i]] = i - left + 1;
      Nb[bl][A[i]]++;
      Pos[i] = A[i];
      TT[i] = i;
    } else
      Nb[bl][A[i]]++, TT[i] = Root[bl][A[i]] + left - 1;
  }
}
void rebuild(int bl) {
  int left = Left[bl], right = Right[bl];
  Max[bl] = 0;
  for (int i = left; i <= right; i++) {
    A[i] = Pos[Father(i)];
    Root[bl][A[i]] = 0;
    Nb[bl][A[i]] = 0;
    A[i] -= Tag[bl];
  }
  Tag[bl] = 0;
  for (int i = left; i <= right; i++) TT[i] = Pos[i] = 0;
}
void Update(int bl, int l, int r, int x) {
  for (int i = l; i <= r; i++)
    if (A[i] > x) A[i] -= x;
}
int Q(int bl, int l, int r, int x) {
  int ret = 0;
  for (int i = l; i <= r; i++)
    if (A[i] == x) ret++;
  return ret;
}
void Task1(int l, int r, int x) {
  if (Block[l] == Block[r]) {
    rebuild(Block[l]);
    Update(Block[l], l, r, x);
    build(Block[l]);
  } else {
    rebuild(Block[l]);
    Update(Block[l], l, Right[Block[l]], x);
    build(Block[l]);
    rebuild(Block[r]);
    Update(Block[r], Left[Block[r]], r, x);
    build(Block[r]);
    for (int i = Block[l] + 1; i < Block[r]; i++) {
      update(i, x);
    }
  }
}
int Query(int l, int r, int x) {
  int ans = 0;
  if (Block[l] == Block[r]) {
    rebuild(Block[l]);
    ans = Q(Block[l], l, r, x);
    build(Block[l]);
  } else {
    rebuild(Block[l]);
    ans = Q(Block[l], l, Right[Block[l]], x);
    build(Block[l]);
    rebuild(Block[r]);
    ans += Q(Block[r], Left[Block[r]], r, x);
    build(Block[r]);
    for (int i = Block[l] + 1; i < Block[r]; i++) {
      if (x <= Max[i] - Tag[i]) ans += Nb[i][x + Tag[i]];
    }
  }
  return ans;
}
int main() {
  Read();
  precalcBlock();
  for (int i = 1; i <= Block[N]; i++) build(i);
  for (int i = 1; i <= M; i++) {
    int type, l, r, x;
    scanf("%d%d%d%d", &type, &l, &r, &x);
    if (type == 1)
      Task1(l, r, x);
    else
      printf("%d\n", Query(l, r, x));
  }
  return 0;
}
