#include <bits/stdc++.h>

class Dsu {
 public:
  Dsu() {}
  explicit Dsu(int n) : dat(n, -1), num_components_(n) {}

  int size() const { return std::size(dat); }
  int root(int v) {
    assert(0 <= v), assert(v < size());
    return dat[v] < 0 ? v : dat[v] = root(dat[v]);
  }
  std::pair<int, int> unite(int u, int v) {
    assert(0 <= u), assert(u < size());
    assert(0 <= v), assert(v < size());
    u = root(u), v = root(v);
    if (u == v) return {u, -1};
    --num_components_;
    if (-dat[u] < -dat[v]) std::swap(u, v);
    dat[u] += dat[v];
    dat[v] = u;
    return {u, v};
  }
  bool same(int u, int v) {
    assert(0 <= u), assert(u < size());
    assert(0 <= v), assert(v < size());
    return root(u) == root(v);
  }
  int size(int v) {
    assert(0 <= v), assert(v < size());
    return -dat[root(v)];
  }
  int num_components() const { return num_components_; }

 private:
  std::vector<int> dat;
  int num_components_;
};

#pragma region my_template

struct Rep {
  struct I {
    int i;
    void operator++() { ++i; }
    int operator*() const { return i; }
    bool operator!=(I o) const { return i < *o; }
  };
  const int l_, r_;
  Rep(int l, int r) : l_(l), r_(r) {}
  Rep(int n) : Rep(0, n) {}
  I begin() const { return {l_}; }
  I end() const { return {r_}; }
};
struct Per {
  struct I {
    int i;
    void operator++() { --i; }
    int operator*() const { return i; }
    bool operator!=(I o) const { return i > *o; }
  };
  const int l_, r_;
  Per(int l, int r) : l_(l), r_(r) {}
  Per(int n) : Per(0, n) {}
  I begin() const { return {r_ - 1}; }
  I end() const { return {l_ - 1}; }
};

template <class F>
struct Fix : private F {
  Fix(F f) : F(f) {}
  template <class... Args>
  decltype(auto) operator()(Args&&... args) const {
    return F::operator()(*this, std::forward<Args>(args)...);
  }
};

template <class T = int>
T scan() {
  T res;
  std::cin >> res;
  return res;
}

template <class T, class U = T>
bool chmin(T& a, U&& b) {
  return b < a ? a = std::forward<U>(b), true : false;
}
template <class T, class U = T>
bool chmax(T& a, U&& b) {
  return a < b ? a = std::forward<U>(b), true : false;
}

#ifndef LOCAL
#define DUMP(...) void(0)
template <int OnlineJudge, int Local>
constexpr int OjLocal = OnlineJudge;
#endif

using namespace std;

#define ALL(c) begin(c), end(c)

#pragma endregion

constexpr int B = OjLocal<1 << 8, 1>;

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);
  cout << fixed << setprecision(20);
  int n = scan();
  int q = scan();
  vector<int> a(n);
  generate(ALL(a), scan<>);

  vector<int> p;
  for (int i = 0; i < n; i += B) p.push_back(i);
  p.push_back(n);
  int m = size(p) - 1;

  vector<deque<pair<int, int>>> vr(m);
  vector<Dsu> d(m);
  vector<int> o(m);
  auto build = [&](int j) {
    vr[j].clear();
    for (int i : Rep(p[j], p[j + 1])) vr[j].emplace_back(a[i], i - p[j]);
    sort(ALL(vr[j]));
    d[j] = Dsu(p[j + 1] - p[j]);
    o[j] = 0;
    int sz = 0;
    for (int l = 0; l < p[j + 1] - p[j];) {
      int r = l;
      while (r < p[j + 1] - p[j] and vr[j][r].first == vr[j][l].first) ++r;
      for (int i : Rep(l + 1, r))
        vr[j][l].second = d[j].unite(vr[j][l].second, vr[j][i].second).first;
      vr[j][sz++] = vr[j][l];
      l = r;
    }
    vr[j].resize(sz);
  };
  auto push = [&](int j) {
    for (int i : Rep(size(vr[j])))
      a[p[j] + vr[j][i].second] = o[j] + vr[j][i].first;
    for (int i : Rep(p[j], p[j + 1])) a[i] = a[p[j] + d[j].root(i - p[j])];
  };

  vector<pair<int, int>> b0, b1, b2;
  auto mrg = [&](int j) {
    b2.clear();
    for (auto it0 = begin(b0), it1 = begin(b1);
         it0 != end(b0) or it1 != end(b1);)
      if (it1 == end(b1) or (it0 != end(b0) and it0->first < it1->first)) {
        b2.push_back(*it0);
        ++it0;
      } else if (it0 == end(b0) or
                 (it1 != end(b1) and it1->first < it0->first)) {
        b2.push_back(*it1);
        ++it1;
      } else if (it0 != end(b0) and it1 != end(b1) and
                 it0->first == it1->first) {
        b2.push_back(*it0);
        b2.back().second = d[j].unite(it0->second, it1->second).first;
        ++it0, ++it1;
      } else
        assert(false);
  };

  for (int j : Rep(m)) build(j);
  while (q--) {
    int tp = scan();
    int l = scan() - 1;
    int r = scan();
    int x = scan();
    if (tp == 1) {
      for (int j : Rep(m)) {
        int s = max(l, p[j]);
        int t = min(r, p[j + 1]);
        if (s == p[j] and t == p[j + 1]) {
          int mx = o[j] + vr[j].back().first;
          if (mx > 2 * x) {
            o[j] -= x;
            for (int i : Rep(size(vr[j]))) {
              if (vr[j][i].first > x) {
                b0 = {begin(vr[j]), begin(vr[j]) + i};
                vr[j].erase(begin(vr[j]), begin(vr[j]) + i);
                b1.clear();
                while (not empty(vr[j]) and vr[j].front().first <= 2 * x)
                  b1.push_back(vr[j].front()), vr[j].pop_front();
                mrg(j);
                while (not empty(b2))
                  vr[j].push_front(b2.back()), b2.pop_back();
                break;
              }
              vr[j][i].first += x;
            }
          } else if (mx > x) {
            for (int i : Per(size(vr[j]))) {
              if (vr[j][i].first <= x) {
                b0 = {(i + 1) + ALL(vr[j])};
                vr[j].erase((i + 1) + ALL(vr[j]));
                b1.clear();
                while (not empty(vr[j]) and
                       vr[j].front().first <= b0.back().first)
                  b1.push_back(vr[j].front()), vr[j].pop_front();
                mrg(j);
                while (not empty(b2))
                  vr[j].push_front(b2.back()), b2.pop_back();
                break;
              }
              vr[j][i].first -= x;
            }
          }
        } else {
          push(j);
          for (int i : Rep(s, t))
            if (a[i] > x) a[i] -= x;
          build(j);
        }
      }
    } else {
      int ans = 0;
      for (int j : Rep(m)) {
        int s = max(l, p[j]);
        int t = min(r, p[j + 1]);
        if (s == p[j] and t == p[j + 1]) {
          auto it = lower_bound(ALL(vr[j]), pair{x - o[j], 0});
          if (it != end(vr[j]) and it->first == x - o[j])
            ans += d[j].size(it->second);
        } else {
          push(j);
          for (int i : Rep(s, t)) ans += a[i] == x;
          build(j);
        }
      }
      cout << ans << '\n';
    }
  }
}
