Problem:
G: Freqs
問題
長さ $N$ の数列 $A = (a_1, a_2, ..., a_N)$ が与えられます。以下で説明されるクエリを $Q$ 回処理してください。クエリは $4$ 種類あります。
クエリ 1: $l, r, x$ が与えられるので、$a_i$ ($l \leq i \leq r$) を $\min(a_i, x)$ に更新する。
クエリ 2: $l, r, x$ が与えられるので、$a_i$ ($l \leq i \leq r$) を $\max(a_i, x)$ に更新する。
クエリ 3: $l, r, x$ が与えられるので、$a_i$ ($l \leq i \leq r$) を $a_i + x$ に更新する。
クエリ 4: $l, r, x, y$ が与えられるので、$l \leq i \leq r$ かつ $x \leq a_i \leq y$ を満たす $i$ の個数を報告する。
入力形式
$N$ $Q$
$a_1$ $a_2$ ... $a_N$
$q_1$
...
$q_Q$
ただし、$q_j$ ($1\leq j \leq Q$) の形式は次のいずれかです。
クエリ 1：
1 $l$ $r$ $x$
クエリ 2：
2 $l$ $r$ $x$
クエリ 3：
3 $l$ $r$ $x$
クエリ 4：
4 $l$ $r$ $x$ $y$
制約
入力は全て整数で与えられる
$1 \leq N \leq 10^5$
$1 \leq Q \leq 10^5$
$-10^9 \leq a_i \leq 10^9$ ($1 \leq i \leq N$)
$1 \leq l_i \leq r_i \leq N$ ($1 \leq i \leq Q$)
クエリ 1, 2, 3 において $-10^9 \leq x_i \leq 10^9$ ($1 \leq i \leq Q$)
クエリ 4 において $-10^{15} \leq x_i \leq y_i \leq 10^{15}$ ($1 \leq i \leq Q$)
出力形式
各クエリ 4 に対して、その答えを一行ずつ出力してください。
入力例1
6 8
3 1 4 1 5 9
4 2 5 3 6
2 2 5 3
3 4 6 3
4 2 5 4 7
3 3 6 -10
4 2 5 -5 5
1 1 6 1
4 1 6 -10 0
出力例1
2
2
3
3
$q_1$ のクエリ 4 について、条件を満たす $i$ は $3$ と $5$ なので、その個数 $2$ を出力します。クエリ 1, 2, 3 の更新により、数列 $A$ は次のように変化していきます。
$q_2$ の直後：
3 3 4 3 5 9
$q_3$ の直後：
3 3 4 6 8 12
$q_5$ の直後：
3 3 -6 -4 -2 2
$q_7$ の直後：
1 1 -6 -4 -2 1
入力例2
10 12
1 -1 -3 9 0 1 -3 7 5 -8
1 1 6 4
4 2 10 3 9
2 4 9 7
3 5 8 -2
2 1 3 1
4 8 10 -10 1
3 2 5 3
4 1 3 3 7
1 2 2 5
4 1 9 1 5
1 3 10 2
4 5 7 -2 4
出力例2
3
1
2
6
3

Submitted solutions:

code_snippet: // AOJ #3170 Freqs
// 2025.5.28

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0, c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

ll Cinll() {
	ll n = 0, c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
    pc('\n');
}

const int MAXN = 100000;
const int BSZ  = 200;
const ll  INF  = (ll)4e18;

int N, Q;
ll A[MAXN];
int nb;
int szb[MAXN/BSZ+5];

ll cm[MAXN/BSZ+5], cM[MAXN/BSZ+5], addv[MAXN/BSZ+5];

ll V[MAXN/BSZ+5][BSZ];

inline void flush_block(int b, bool f_sort){
    int start = b*BSZ;
    ll cap_max = cm[b], cap_min = cM[b], ad = addv[b];
    int s = szb[b];
    for(int i=0;i<s;i++){
        int idx = start + i;
        ll v = A[idx];
        if(v > cap_max) v = cap_max;
        if(v < cap_min) v = cap_min;
        v += ad;
        A[idx] = v;
        V[b][i] = v;
    }
    if(f_sort) sort(V[b], V[b]+s);
    cm[b] = INF;
    cM[b] = -INF;
    addv[b] = 0;
}

int main(){
    N = Cin(), Q = Cin();
    for(int i=0;i<N;i++) A[i] = Cin();

    nb = (N + BSZ - 1) / BSZ;
    for(int b=0;b<nb;b++){
        int start = b*BSZ;
        int s = min(BSZ, N - start);
        szb[b] = s;
        for(int i=0;i<s;i++) V[b][i] = A[start + i];
        sort(V[b], V[b]+s);
        cm[b] = INF;
        cM[b] = -INF;
        addv[b] = 0;
    }

    while(Q--){
        int t = Cin(), l = Cin()-1, r = Cin()-1;
        ll x = Cinll();
        ll y;
        if(t==4) y = Cinll();

        int bL = l/BSZ, bR = r/BSZ;
        int ans = 0;
        if(bL == bR){
            flush_block(bL, true);
            for(int i=l;i<=r;i++){
                if(t==1)      A[i] = min(A[i], x);
                else if(t==2) A[i] = max(A[i], x);
                else if(t==3) A[i] += x;
                else if(t==4) if(A[i]>=x && A[i]<=y) ans++;
            }
            int start=bL*BSZ, s=szb[bL];
            for(int i=0;i<s;i++) V[bL][i] = A[start+i];
            sort(V[bL], V[bL]+s);
        } else {
            flush_block(bL, false);
            flush_block(bR, false);

            int endL = (bL+1)*BSZ;
            for(int i=l;i<endL;i++){
                if(t==1)      A[i] = min(A[i], x);
                else if(t==2) A[i] = max(A[i], x);
                else if(t==3) A[i] += x;
                else if(t==4) if(A[i]>=x && A[i]<=y) ans++;
            }
            int startR = bR*BSZ;
            for(int i=startR;i<=r;i++){
                if(t==1)      A[i] = min(A[i], x);
                else if(t==2) A[i] = max(A[i], x);
                else if(t==3) A[i] += x;
                else if(t==4) if(A[i]>=x && A[i]<=y) ans++;
            }

            for(int b=bL+1; b<bR; b++){
                if(t==1){
                    ll lim = x - addv[b];
                    if(lim < cm[b]) cm[b] = lim;
                    if(cM[b] > cm[b]) cM[b] = cm[b];
                }
                else if(t==2){
                    ll lim = x - addv[b];
                    if(lim > cM[b]) cM[b] = lim;
                    if(cM[b] > cm[b]) cm[b] = cM[b];
                }
                else if(t==3) addv[b] += x;
                else {
                    ll tl = x - addv[b], tr = y - addv[b];
                    if(tl > cm[b] || tr < cM[b]) continue;
                    ll lo = tl, hi = tr;
                    if(cM[b] >= tl) lo = -INF;
                    if(cm[b] <= tr) hi = +INF;
                    int cnt = upper_bound(V[b], V[b]+szb[b], hi)
                            - lower_bound(V[b], V[b]+szb[b], lo);
                    ans += cnt;
                }
            }

            flush_block(bL, true);
            flush_block(bR, true);
        }
        if(t==4) Cout(ans);
    }
    return 0;
}
accuracy: 1
time_ms: 1200
memory_kb: 4940
final_rank: 8

code_snippet: // AOJ #3170 Freqs
// 2025.3.21

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0; int c = gc();
	if (c == '-') {	c = gc();
		do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
		return -n;
	}
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(ll n) { // 整数の表示（出力）
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

struct Block {
    int L, R;
    vector<ll> a;
    vector<ll> s;
    ll lz;
    ll mn, mx;

    void init(int L, int R, const vector<ll>& arr) {
        this->L = L; this->R = R;
        a.resize(R - L + 1);
        for (int i = L; i <= R; i++) a[i - L] = arr[i];
        lz = 0;
        rebuild();
    }
    void rebuild() {
        s = a;
        sort(s.begin(), s.end());
        if(!s.empty()){
            mn = s.front() + lz;
            mx = s.back() + lz;
        } else mn = mx = 0;
    }
    void push(){
        if(lz){
            for(auto &v : a) v += lz;
            lz = 0;
            rebuild();
        }
    }
    void add(ll x) {
        lz += x;
        mn += x;
        mx += x;
    }
    void chmin(ll x) {
        if(mx <= x) return;
        if(mn >= x){
            lz = 0;
            for(auto &v : a) v = x;
            rebuild();
            return;
        }
        push();
        for(auto &v : a) if(v > x) v = x;
        rebuild();
    }
    void chmax(ll x) {
        if(mn >= x) return;
        if(mx <= x){
            lz = 0;
            for(auto &v : a) v = x;
            rebuild();
            return;
        }
        push();
        for(auto &v : a) if(v < x) v = x;
        rebuild();
    }
    void add_range(int l, int r, ll x){
        push();
        for (int i = l; i <= r; i++) a[i] += x;
        rebuild();
    }
    void chmin_range(int l, int r, ll x){
        push();
        for (int i = l; i <= r; i++) if(a[i] > x) a[i] = x;
        rebuild();
    }
    void chmax_range(int l, int r, ll x){
        push();
        for (int i = l; i <= r; i++) if(a[i] < x) a[i] = x;
        rebuild();
    }
    int count_range(int l, int r, ll x, ll y){
        int cnt = 0;
        push();
        for (int i = l; i <= r; i++){
            ll v = a[i];
            if(v >= x && v <= y) cnt++;
        }
        return cnt;
    }
    int query(ll x, ll y){
        ll Lbound = x - lz, Rbound = y - lz;
        return (int)(upper_bound(s.begin(), s.end(), Rbound) - lower_bound(s.begin(), s.end(), Lbound));
    }
};

int main(){
    int n = Cin(), q = Cin();
    vector<ll> arr(n);
    for (int i = 0; i < n; i++) arr[i] = Cin();

    int bs = max(1, (int)sqrt(n));
    vector<Block> B;
    for (int i = 0; i < n; i += bs) {
        int r = min(n - 1, i + bs - 1);
        Block b;
        b.init(i, r, arr);
        B.push_back(b);
    }

    while(q--){
        int t = gc() & 0xf; gc();
        if(t == 1){
            int l = Cin()-1, r = Cin()-1;
            ll x = Cin();
            for(auto &b : B){
                if(b.R < l || b.L > r) continue;
                if(l <= b.L && b.R <= r) b.chmin(x);
                else {
                    int li = max(l, b.L) - b.L, ri = min(r, b.R) - b.L;
                    b.chmin_range(li, ri, x);
                }
            }
        } else if(t == 2){
            int l = Cin()-1, r = Cin()-1;
            ll x = Cin();
            for(auto &b : B){
                if(b.R < l || b.L > r) continue;
                if(l <= b.L && b.R <= r) b.chmax(x);
                else {
                    int li = max(l, b.L) - b.L, ri = min(r, b.R) - b.L;
                    b.chmax_range(li, ri, x);
                }
            }
        } else if(t == 3){
            int l = Cin()-1, r = Cin()-1;
            ll x = Cin();
            for(auto &b : B){
                if(b.R < l || b.L > r) continue;
                if(l <= b.L && b.R <= r) b.add(x);
                else {
                    int li = max(l, b.L) - b.L, ri = min(r, b.R) - b.L;
                    b.add_range(li, ri, x);
                }
            }
        } else if(t == 4){
            int l = Cin()-1, r = Cin()-1;
            ll x = Cin(), y= Cin();
            ll ans = 0;
            for(auto &b : B){
                if(b.R < l || b.L > r) continue;
                if(l <= b.L && b.R <= r)
                    ans += b.query(x, y);
                else {
                    int li = max(l, b.L) - b.L, ri = min(r, b.R) - b.L;
                    ans += b.count_range(li, ri, x, y);
                }
            }
            Cout(ans);
        }
    }
    return 0;
}
accuracy: 0.09523809523809523
time_ms: 1290
memory_kb: 5308
final_rank: 20

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#include <thread>
#include <chrono>
#define allof(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
using namespace std;

template<typename F, typename S>
std::ostream &operator << (std::ostream &dest, const std::pair<F, S> &p) {
    dest << p.first << ' ' << p.second;
    return dest;
}

template<typename A, typename B>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t);
    return dest;
}

template<typename A, typename B, typename C>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t);
    return dest;
}

template<typename A, typename B, typename C, typename D>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C, D> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << ' ' << std::get<3>(t);
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<std::vector<T>> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz; i++) {
        int m = v[i].size();
        for (int j = 0; j < m; j++) dest << v[i][j] << (i != sz - 1 && j == m - 1 ? '\n' : ' ');
    }
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<T> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T, size_t sz>
std::ostream &operator << (std::ostream &dest, const std::array<T, sz> &v) {
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::set<T> &v) {
    for (auto itr = v.begin(); itr != v.end();) {
        dest << *itr;
        itr++;
        if (itr != v.end()) dest << ' ';
    }
    return dest;
}

template<typename T, typename E>
std::ostream &operator << (std::ostream &dest, const std::map<T, E> &v) {
    for (auto itr = v.begin(); itr != v.end(); ) {
        dest << '(' << itr->first << ", " << itr->second << ')';
        itr++;
        if (itr != v.end()) dest << '\n';
    }
    return dest;
}

template<typename T>
std::vector<T> make_vec(size_t sz, T val) { return std::vector<T>(sz, val); }

template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail) {
    return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}

template<typename T>
std::vector<T> read_vec(size_t sz) {
    std::vector<T> v(sz);
    for (int i = 0; i < (int)sz; i++) std::cin >> v[i];
    return v;
}

template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail) {
    auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
    for (int i = 0; i < (int)sz; i++) v[i] = read_vec<T>(tail...);
    return v;
}

template<typename T, size_t size>
auto make_array(T x) { 
    std::array<T, size> res;
    res.fill(x);
    return res;
}

template<typename T, size_t size, size_t size2, size_t... Tail>
auto make_array(T x) {
    std::array<decltype(make_array<T, size2, Tail...>(x)), size> res;
    res.fill(make_array<T, size2, Tail...>(x));
    return res;
}


// x / y以上の最小の整数
ll ceil_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? y - 1 : 0)) / y;
}

// x / y以下の最大の整数
ll floor_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? 0 : -y + 1)) / y;
}

void io_init() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
}



#include <limits>

template<typename T>
struct add_min_function{
  using F = add_min_function<T>;
  T add, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  add_min_function(): add(0), upper(inf){}
  add_min_function(T _add, T _upper): add(_add), upper(_upper){}
  // g(f(x))
  static F merge(const F &f, const F &g){return {f.add + g.add, std::min(g.upper, f.upper + g.add)};}
  T fx(T x){return std::min(x + add, upper);}
  bool operator == (const F &r)const{return add == r.add && upper == r.upper;}
};

// f(x) = min(max(x + a, b), c)
template<typename T>
struct clamp_function{
  T add, lower, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function(): add(0), lower(minf), upper(inf){}
  clamp_function(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper){lower = std::min(_lower, _upper);}
  // g(f(x))
  static clamp_function<T> merge(const clamp_function<T> &f, const clamp_function<T> &g){
    return {f.add + g.add, std::max(g.lower, std::min(f.upper, f.lower) + g.add), std::min(g.upper, std::max(g.lower, f.upper + g.add))};
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  bool operator == (const clamp_function<T> &r)const{return add == r.add && lower == r.lower && upper == r.upper;}
};
// f(x) = min(max(x + a, b), c)
// min部分によって減少した値をスコアとする
template<typename T, typename Tsum>
struct clamp_function_score{
public:
  T add, lower, upper, score_upper;
  Tsum score_sum;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function_score(): add(0), lower(minf), upper(inf), score_upper(inf), score_sum(0){}
  clamp_function_score(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper), score_upper(_upper), score_sum(0){lower = std::min(_lower, _upper);}
private:
  clamp_function_score(T _add, T _lower, T _upper, T _supper, Tsum _ssum): add(_add), lower(_lower), upper(_upper), score_upper(_supper), score_sum(_ssum){}
public:
  // g(f(x))
  static clamp_function_score<T, Tsum> merge(const clamp_function_score<T, Tsum> &f, const clamp_function_score<T, Tsum> &g){
    T _add = f.add + g.add;
    T _lower = std::max(g.lower, std::min(f.upper, f.lower) + g.add);
    T _upper = std::min(g.upper, std::max(g.lower, f.upper + g.add));
    _lower = std::min(_lower, _upper);
    Tsum _ssum = f.score_sum + g.score_sum;
    if(f.lower == f.upper){
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.score_upper + g.add, _ssum};
    }else if(f.lower + g.add >= g.score_upper){
      assert(_lower == _upper);
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.lower + g.add, _ssum};
    }else{
      return {_add, _lower, _upper, std::min(f.score_upper + g.add, g.score_upper), _ssum};
    }
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  Tsum fx_score(T x){
    return score_sum + std::max((T)0, x + add - score_upper);
  }
  bool operator == (const clamp_function_score<T, Tsum> &r)const{return add == r.add && lower == r.lower && upper == r.upper && score_upper == r.score_upper && score_sum == r.score_sum;}
};



template<typename T>
struct prefixsum_min{
  T sum, pmin;
  static prefixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static prefixsum_min<T> merge(prefixsum_min<T> a, prefixsum_min<T> b){
    if(b.pmin == std::numeric_limits<T>::max() / 2) return a;
    return {a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin)};
  }
};
template<typename T>
struct prefixsum_max{
  T sum, pmax;
  static prefixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static prefixsum_max<T> merge(prefixsum_max<T> a, prefixsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min() / 2) return a;
    return {a.sum + b.sum, std::max(a.pmax, a.sum + b.pmax)};
  }
};
template<typename T>
struct suffixsum_min{
  T sum, smin;
  static suffixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static suffixsum_min<T> merge(suffixsum_min<T> a, suffixsum_min<T> b){
    if(a.smin == std::numeric_limits<T>::max() / 2) return b;
    return {a.sum + b.sum, std::min(b.smin, b.sum + a.smin)};
  }
};
template<typename T>
struct suffixsum_max{
  T sum, smax;
  static suffixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static suffixsum_max<T> merge(suffixsum_max<T> a, suffixsum_max<T> b){
    if(a.smax == std::numeric_limits<T>::min() / 2) return b;
    return {a.sum + b.sum, std::max(b.smax, b.sum + a.smax)};
  }
};
template<typename T>
struct substringsum_max{
  T sum, pmax, smax, ssmax; // {区間全体のsum, prefixsumのmax, suffixsumのmax, substringsumのmax}
  static substringsum_max<T> id(){
    return {0, std::numeric_limits<T>::min(), 0, 0};
  }
  static substringsum_max<T> merge(substringsum_max<T> a, substringsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min()) return a;
    if(a.pmax == std::numeric_limits<T>::min()) return b;
    T sum = a.sum + b.sum;
    T pmax = std::max(a.pmax, a.sum + b.pmax);
    T smax = std::max(a.smax + b.sum, b.smax);
    return {sum, pmax, smax, std::max({a.ssmax, b.ssmax, pmax, smax})};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax
struct excess_value{
public:
  int rank, sum, pmin, pmax;
  static constexpr int inf = 1 << 30;
  excess_value(): rank(inf), pmin(inf), pmax(-inf){}
  excess_value(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum){}
private:
  excess_value(int a, int b, int c, int d): rank(a), sum(b), pmin(c), pmax(d){}
public:
  static excess_value merge(excess_value a, excess_value b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), std::max(a.pmax, a.sum + b.pmax)};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax, 接尾辞のmin, 接尾辞のmax
struct excess_value2{
public:
  int rank, sum, pmin, pmax, smin, smax;
  static constexpr int inf = 1 << 30;
  excess_value2(): rank(inf), pmin(inf), pmax(-inf), smin(inf), smax(-inf){}
  excess_value2(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum), smin(sum), smax(sum){}
private:
  excess_value2(int a, int b, int c, int d, int e, int f): rank(a), sum(b), pmin(c), pmax(d), smin(e), smax(f){}
public:
  static excess_value2 merge(excess_value2 a, excess_value2 b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), 
    std::max(a.pmax, a.sum + b.pmax), std::min(a.smin + b.sum, b.smin), std::max(a.smax + b.sum, b.smax)};
  }
};


// https://probablydance.com/2016/12/27/i-wrote-a-faster-sorting-algorithm/
struct PartitionInfo
{
    PartitionInfo()
        : count(0)
    {
    }
 
    union
    {
        size_t count;
        size_t offset;
    };
    size_t next_offset;
};
 
template<typename It, typename ExtractKey>
void ska_byte_sort(It begin, It end, ExtractKey & extract_key)
{
    PartitionInfo partitions[256];
    for (It it = begin; it != end; ++it)
    {
        ++partitions[extract_key(*it)].count;
    }
    uint8_t remaining_partitions[256];
    size_t total = 0;
    int num_partitions = 0;
    for (int i = 0; i < 256; ++i)
    {
        size_t count = partitions[i].count;
        if (count)
        {
            partitions[i].offset = total;
            total += count;
            remaining_partitions[num_partitions] = i;
            ++num_partitions;
        }
        partitions[i].next_offset = total;
    }
    for (uint8_t * last_remaining = remaining_partitions + num_partitions, * end_partition = remaining_partitions + 1; last_remaining > end_partition;)
    {
        last_remaining = custom_std_partition(remaining_partitions, last_remaining, [&](uint8_t partition)
        {
            size_t & begin_offset = partitions[partition].offset;
            size_t & end_offset = partitions[partition].next_offset;
            if (begin_offset == end_offset)
                return false;
 
            unroll_loop_four_times(begin + begin_offset, end_offset - begin_offset, [partitions = partitions, begin, &extract_key](It it)
            {
                uint8_t this_partition = extract_key(*it);
                size_t offset = partitions[this_partition].offset++;
                std::iter_swap(it, begin + offset);
            });
            return begin_offset != end_offset;
        });
    }
}

template<typename T>
struct range_add_chmin_chmax_range_freq {
  private:
    static constexpr T inf = std::numeric_limits<T>::max();
    static constexpr T minf = std::numeric_limits<T>::min();
    using F = clamp_function<T>;
    int N;
    std::vector<T> V, B;
    std::vector<F> lz;
    std::vector<bool> is_sorted;
    static constexpr int sq = 128;
  
  public:
    range_add_chmin_chmax_range_freq(int _N) : range_add_chmin_chmax_range_freq(std::vector<T>(_N, 0)) {}
    range_add_chmin_chmax_range_freq(const std::vector<T> &_V) : N(_V.size()), V(_V), lz((N + sq - 1) / sq, F()), is_sorted((N + sq - 1) / sq, true) {
        B = V;
        for (int i = 0; i < (N + sq - 1) / sq; i++) {
            int L = i * sq;
            int R = std::min(L + sq, N);
            std::sort(B.begin() + L, B.begin() + R);
        }
    }

    // [l, r)の x <- min(max(x + add, lower), upper)
    void apply(int l, int r, T add, T lower, T upper) {
        assert(l <= r && lower <= upper);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        F f{add, lower, upper};
        if (l < lb * sq) is_sorted[lb - 1] = false;
        if (rb * sq < r) is_sorted[rb] = false;
        if (lb > rb) {
            int L = rb * sq, R = std::min(N, L + sq);
            for (int i = L; i < R; i++) {
                V[i] = lz[rb].fx(V[i]);
                if (l <= i && i < r) V[i] = f.fx(V[i]);
            }
            lz[rb] = F{};
            return;
        }
        if (l < lb * sq) {
            int L = (lb - 1) * sq, R = std::min(N, L + sq);
            for (int i = L; i < l; i++) {
                V[i] = lz[lb - 1].fx(V[i]);
            }
            for (int i = l; i < R; i++) {
                V[i] = f.fx(lz[lb - 1].fx(V[i]));
            }
            lz[lb - 1] = F{};
        }
        if (rb * sq < r) {
            int L = rb * sq, R = std::min(N, L + sq);
            for (int i = L; i < r; i++) {
                V[i] = f.fx(lz[rb].fx(V[i]));
            }
            for (int i = r; i < R; i++) {
                V[i] = lz[rb].fx(V[i]);
            }
            lz[rb] = F{};
        }
        for (int i = lb; i < rb; i++) {
            lz[i] = F::merge(lz[i], f);
        }
    }

    // [l, r)のx以上の最小要素
    T lower_bound(int l, int r, T x) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        T res = inf;
        if (lb > rb) {
            for (int i = l; i < r; i++) {
                T y = lz[rb].fx(V[i]);
                if (y >= x) res = std::min(res, y);
            }
            return res;
        }
        for (int i = l; i < lb * sq; i++) {
            T y = lz[lb - 1].fx(V[i]);
            if (y >= x) res = std::min(res, y);
        }
        for (int i = rb * sq; i < r; i++) {
            T y = lz[rb].fx(V[i]);
            if (y >= x) res = std::min(res, y);
        }
        for (int i = lb; i < rb; i++) {
            if (lz[i].upper < x) continue;
            int L = i * sq, R = std::min(N, L + sq);
            if (!is_sorted[i]) {
                for (int j = L; j < R; j++) B[j] = V[j];
                std::sort(B.begin() + L, B.begin() + R);
                is_sorted[i] = true;
            }
            auto itr = std::lower_bound(B.begin() + L, B.begin() + R, x - lz[i].add);
            if (lz[i].lower >= x && itr != B.begin() + L) {
                res = std::min(res, lz[i].lower);
            }
            if (itr != B.begin() + R) {
                res = std::min(res, lz[i].fx(*itr));
            }
        }
        return res;
    }

    // [l, r)のrx未満の要素数
    int range_freq(int l, int r, T rx) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        int res = 0;
        if (lb > rb) {
            for (int i = l; i < r; i++) {
                T y = lz[rb].fx(V[i]);
                if (y < rx) res++;
            }
            return res;
        }
        for (int i = l; i < lb * sq; i++) {
            T y = lz[lb - 1].fx(V[i]);
            if (y < rx) res++;
        }
        for (int i = rb * sq; i < r; i++) {
            T y = lz[rb].fx(V[i]);
            if (y < rx) res++;
        }
        for (int i = lb; i < rb; i++) {
            if (lz[i].lower >= rx) continue;
            int L = i * sq, R = std::min(N, L + sq);
            if (lz[i].upper < rx) {
                res += R - L;
                continue;
            }
            if (!is_sorted[i]) {
                for (int j = L; j < R; j++) B[j] = V[j];
                std::sort(B.begin() + L, B.begin() + R);
                is_sorted[i] = true;
            }
            res += std::lower_bound(B.begin() + L, B.begin() + R, rx - lz[i].add) - (B.begin() + L);
        }
        return res;
    }
};

int main() {
    io_init();
    int N, Q;
    std::cin >> N >> Q;
    auto A = read_vec<ll>(N);
    range_add_chmin_chmax_range_freq<ll> F(A);

    static constexpr ll inf = 1LL << 60, minf = -inf;
    for (int i = 0; i < Q; i++) {
        int t, l, r;
        ll x;
        std::cin >> t >> l >> r >> x;
        l--;
        if (t == 1) {
            F.apply(l, r, 0, minf, x);
        } else if (t == 2) {
            F.apply(l, r, 0, x, inf);
        } else if (t == 3) {
            F.apply(l, r, x, minf, inf);
        } else {
            ll y;
            std::cin >> y;
            ll ans = F.range_freq(l, r, y + 1) - F.range_freq(l, r, x);
            std::cout << ans << '\n';
        }
    }
}
accuracy: 1
time_ms: 1010
memory_kb: 5468
final_rank: 6

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#include <thread>
#include <chrono>
#define allof(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
using namespace std;

template<typename F, typename S>
std::ostream &operator << (std::ostream &dest, const std::pair<F, S> &p) {
    dest << p.first << ' ' << p.second;
    return dest;
}

template<typename A, typename B>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t);
    return dest;
}

template<typename A, typename B, typename C>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t);
    return dest;
}

template<typename A, typename B, typename C, typename D>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C, D> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << ' ' << std::get<3>(t);
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<std::vector<T>> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz; i++) {
        int m = v[i].size();
        for (int j = 0; j < m; j++) dest << v[i][j] << (i != sz - 1 && j == m - 1 ? '\n' : ' ');
    }
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<T> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T, size_t sz>
std::ostream &operator << (std::ostream &dest, const std::array<T, sz> &v) {
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::set<T> &v) {
    for (auto itr = v.begin(); itr != v.end();) {
        dest << *itr;
        itr++;
        if (itr != v.end()) dest << ' ';
    }
    return dest;
}

template<typename T, typename E>
std::ostream &operator << (std::ostream &dest, const std::map<T, E> &v) {
    for (auto itr = v.begin(); itr != v.end(); ) {
        dest << '(' << itr->first << ", " << itr->second << ')';
        itr++;
        if (itr != v.end()) dest << '\n';
    }
    return dest;
}

template<typename T>
std::vector<T> make_vec(size_t sz, T val) { return std::vector<T>(sz, val); }

template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail) {
    return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}

template<typename T>
std::vector<T> read_vec(size_t sz) {
    std::vector<T> v(sz);
    for (int i = 0; i < (int)sz; i++) std::cin >> v[i];
    return v;
}

template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail) {
    auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
    for (int i = 0; i < (int)sz; i++) v[i] = read_vec<T>(tail...);
    return v;
}

template<typename T, size_t size>
auto make_array(T x) { 
    std::array<T, size> res;
    res.fill(x);
    return res;
}

template<typename T, size_t size, size_t size2, size_t... Tail>
auto make_array(T x) {
    std::array<decltype(make_array<T, size2, Tail...>(x)), size> res;
    res.fill(make_array<T, size2, Tail...>(x));
    return res;
}


// x / y以上の最小の整数
ll ceil_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? y - 1 : 0)) / y;
}

// x / y以下の最大の整数
ll floor_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? 0 : -y + 1)) / y;
}

void io_init() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
}



#include <limits>

template<typename T>
struct add_min_function{
  using F = add_min_function<T>;
  T add, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  add_min_function(): add(0), upper(inf){}
  add_min_function(T _add, T _upper): add(_add), upper(_upper){}
  // g(f(x))
  static F merge(const F &f, const F &g){return {f.add + g.add, std::min(g.upper, f.upper + g.add)};}
  T fx(T x){return std::min(x + add, upper);}
  bool operator == (const F &r)const{return add == r.add && upper == r.upper;}
};

// f(x) = min(max(x + a, b), c)
template<typename T>
struct clamp_function{
  T add, lower, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function(): add(0), lower(minf), upper(inf){}
  clamp_function(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper){lower = std::min(_lower, _upper);}
  // g(f(x))
  static clamp_function<T> merge(const clamp_function<T> &f, const clamp_function<T> &g){
    return {f.add + g.add, std::max(g.lower, std::min(f.upper, f.lower) + g.add), std::min(g.upper, std::max(g.lower, f.upper + g.add))};
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  bool operator == (const clamp_function<T> &r)const{return add == r.add && lower == r.lower && upper == r.upper;}
};
// f(x) = min(max(x + a, b), c)
// min部分によって減少した値をスコアとする
template<typename T, typename Tsum>
struct clamp_function_score{
public:
  T add, lower, upper, score_upper;
  Tsum score_sum;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function_score(): add(0), lower(minf), upper(inf), score_upper(inf), score_sum(0){}
  clamp_function_score(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper), score_upper(_upper), score_sum(0){lower = std::min(_lower, _upper);}
private:
  clamp_function_score(T _add, T _lower, T _upper, T _supper, Tsum _ssum): add(_add), lower(_lower), upper(_upper), score_upper(_supper), score_sum(_ssum){}
public:
  // g(f(x))
  static clamp_function_score<T, Tsum> merge(const clamp_function_score<T, Tsum> &f, const clamp_function_score<T, Tsum> &g){
    T _add = f.add + g.add;
    T _lower = std::max(g.lower, std::min(f.upper, f.lower) + g.add);
    T _upper = std::min(g.upper, std::max(g.lower, f.upper + g.add));
    _lower = std::min(_lower, _upper);
    Tsum _ssum = f.score_sum + g.score_sum;
    if(f.lower == f.upper){
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.score_upper + g.add, _ssum};
    }else if(f.lower + g.add >= g.score_upper){
      assert(_lower == _upper);
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.lower + g.add, _ssum};
    }else{
      return {_add, _lower, _upper, std::min(f.score_upper + g.add, g.score_upper), _ssum};
    }
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  Tsum fx_score(T x){
    return score_sum + std::max((T)0, x + add - score_upper);
  }
  bool operator == (const clamp_function_score<T, Tsum> &r)const{return add == r.add && lower == r.lower && upper == r.upper && score_upper == r.score_upper && score_sum == r.score_sum;}
};



template<typename T>
struct prefixsum_min{
  T sum, pmin;
  static prefixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static prefixsum_min<T> merge(prefixsum_min<T> a, prefixsum_min<T> b){
    if(b.pmin == std::numeric_limits<T>::max() / 2) return a;
    return {a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin)};
  }
};
template<typename T>
struct prefixsum_max{
  T sum, pmax;
  static prefixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static prefixsum_max<T> merge(prefixsum_max<T> a, prefixsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min() / 2) return a;
    return {a.sum + b.sum, std::max(a.pmax, a.sum + b.pmax)};
  }
};
template<typename T>
struct suffixsum_min{
  T sum, smin;
  static suffixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static suffixsum_min<T> merge(suffixsum_min<T> a, suffixsum_min<T> b){
    if(a.smin == std::numeric_limits<T>::max() / 2) return b;
    return {a.sum + b.sum, std::min(b.smin, b.sum + a.smin)};
  }
};
template<typename T>
struct suffixsum_max{
  T sum, smax;
  static suffixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static suffixsum_max<T> merge(suffixsum_max<T> a, suffixsum_max<T> b){
    if(a.smax == std::numeric_limits<T>::min() / 2) return b;
    return {a.sum + b.sum, std::max(b.smax, b.sum + a.smax)};
  }
};
template<typename T>
struct substringsum_max{
  T sum, pmax, smax, ssmax; // {区間全体のsum, prefixsumのmax, suffixsumのmax, substringsumのmax}
  static substringsum_max<T> id(){
    return {0, std::numeric_limits<T>::min(), 0, 0};
  }
  static substringsum_max<T> merge(substringsum_max<T> a, substringsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min()) return a;
    if(a.pmax == std::numeric_limits<T>::min()) return b;
    T sum = a.sum + b.sum;
    T pmax = std::max(a.pmax, a.sum + b.pmax);
    T smax = std::max(a.smax + b.sum, b.smax);
    return {sum, pmax, smax, std::max({a.ssmax, b.ssmax, pmax, smax})};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax
struct excess_value{
public:
  int rank, sum, pmin, pmax;
  static constexpr int inf = 1 << 30;
  excess_value(): rank(inf), pmin(inf), pmax(-inf){}
  excess_value(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum){}
private:
  excess_value(int a, int b, int c, int d): rank(a), sum(b), pmin(c), pmax(d){}
public:
  static excess_value merge(excess_value a, excess_value b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), std::max(a.pmax, a.sum + b.pmax)};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax, 接尾辞のmin, 接尾辞のmax
struct excess_value2{
public:
  int rank, sum, pmin, pmax, smin, smax;
  static constexpr int inf = 1 << 30;
  excess_value2(): rank(inf), pmin(inf), pmax(-inf), smin(inf), smax(-inf){}
  excess_value2(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum), smin(sum), smax(sum){}
private:
  excess_value2(int a, int b, int c, int d, int e, int f): rank(a), sum(b), pmin(c), pmax(d), smin(e), smax(f){}
public:
  static excess_value2 merge(excess_value2 a, excess_value2 b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), 
    std::max(a.pmax, a.sum + b.pmax), std::min(a.smin + b.sum, b.smin), std::max(a.smax + b.sum, b.smax)};
  }
};


template<typename T>
struct range_add_chmin_chmax_range_freq {
  private:
    static constexpr T inf = std::numeric_limits<T>::max();
    static constexpr T minf = std::numeric_limits<T>::min();
    using F = clamp_function<T>;
    int N;
    std::vector<T> V, B;
    std::vector<F> lz;
    std::vector<bool> is_sorted;
    static constexpr int sq = 256;
  
  public:
    range_add_chmin_chmax_range_freq(int _N) : range_add_chmin_chmax_range_freq(std::vector<T>(_N, 0)) {}
    range_add_chmin_chmax_range_freq(const std::vector<T> &_V) : N(_V.size()), V(_V), lz((N + sq - 1) / sq, F()), is_sorted((N + sq - 1) / sq, true) {
        B = V;
        for (int i = 0; i < (N + sq - 1) / sq; i++) {
            int L = i * sq;
            int R = std::min(L + sq, N);
            std::sort(B.begin() + L, B.begin() + R);
        }
    }

    // [l, r)の x <- min(max(x + add, lower), upper)
    void apply(int l, int r, T add, T lower, T upper) {
        assert(l <= r && lower <= upper);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        F f{add, lower, upper};
        if (l < lb * sq) is_sorted[lb - 1] = false;
        if (rb * sq < r) is_sorted[rb] = false;
        if (lb > rb) {
            int L = rb * sq, R = std::min(N, L + sq);
            for (int i = L; i < R; i++) {
                V[i] = lz[rb].fx(V[i]);
                if (l <= i && i < r) V[i] = f.fx(V[i]);
            }
            lz[rb] = F{};
            return;
        }
        if (l < lb * sq) {
            int L = (lb - 1) * sq, R = std::min(N, L + sq);
            for (int i = L; i < l; i++) {
                V[i] = lz[lb - 1].fx(V[i]);
            }
            for (int i = l; i < R; i++) {
                V[i] = f.fx(lz[lb - 1].fx(V[i]));
            }
            lz[lb - 1] = F{};
        }
        if (rb * sq < r) {
            int L = rb * sq, R = std::min(N, L + sq);
            for (int i = L; i < r; i++) {
                V[i] = f.fx(lz[rb].fx(V[i]));
            }
            for (int i = r; i < R; i++) {
                V[i] = lz[rb].fx(V[i]);
            }
            lz[rb] = F{};
        }
        for (int i = lb; i < rb; i++) {
            lz[i] = F::merge(lz[i], f);
        }
    }

    /*
    // [l, r)のx以上の最小要素
    T lower_bound(int l, int r, T x) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        T res = inf;
        if (lb >= rb) {
            for (int i = l; i < r; i++) {
                if (V[i] >= x) res = std::min(res, V[i]);
            }
            return res;
        }
        //
        return res;
    }
    */

    // [l, r)のrx未満の要素数
    int range_freq(int l, int r, T rx) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        int res = 0;
        if (lb > rb) {
            for (int i = l; i < r; i++) {
                T y = lz[rb].fx(V[i]);
                if (y < rx) res++;
            }
            return res;
        }
        for (int i = l; i < lb * sq; i++) {
            T y = lz[lb - 1].fx(V[i]);
            if (y < rx) res++;
        }
        for (int i = rb * sq; i < r; i++) {
            T y = lz[rb].fx(V[i]);
            if (y < rx) res++;
        }
        for (int i = lb; i < rb; i++) {
            if (lz[i].lower >= rx) continue;
            int L = i * sq, R = std::min(N, L + sq);
            if (lz[i].upper < rx) {
                res += R - L;
                continue;
            }
            if (!is_sorted[i]) {
                for (int j = L; j < R; j++) B[j] = V[j];
                std::sort(B.begin() + L, B.begin() + R);
                is_sorted[i] = true;
            }
            res += std::lower_bound(B.begin() + L, B.begin() + R, rx - lz[i].add) - (B.begin() + L);
        }
        return res;
    }
    /*

    // [l, r)のrx未満の要素の和
    T range_freq_sum(int l, int r, T rx) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        T res = 0;
        if (lb >= rb) {
            for (int i = l; i < r; i++) {
                if (V[i] < rx) res += V[i];
            }
            return res;
        }
        //
        return res;
    }
    */
};

int main() {
    io_init();
    int N, Q;
    std::cin >> N >> Q;
    auto A = read_vec<ll>(N);
    range_add_chmin_chmax_range_freq<ll> F(A);

    static constexpr ll inf = 1LL << 60, minf = -inf;
    for (int i = 0; i < Q; i++) {
        int t, l, r;
        ll x;
        std::cin >> t >> l >> r >> x;
        l--;
        if (t == 1) {
            F.apply(l, r, 0, minf, x);
        } else if (t == 2) {
            F.apply(l, r, 0, x, inf);
        } else if (t == 3) {
            F.apply(l, r, x, minf, inf);
        } else {
            ll y;
            std::cin >> y;
            ll ans = F.range_freq(l, r, y + 1) - F.range_freq(l, r, x);
            std::cout << ans << '\n';
        }
    }
}
accuracy: 1
time_ms: 1080
memory_kb: 5464
final_rank: 7

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#include <thread>
#include <chrono>
#define allof(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
using namespace std;

template<typename F, typename S>
std::ostream &operator << (std::ostream &dest, const std::pair<F, S> &p) {
    dest << p.first << ' ' << p.second;
    return dest;
}

template<typename A, typename B>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t);
    return dest;
}

template<typename A, typename B, typename C>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t);
    return dest;
}

template<typename A, typename B, typename C, typename D>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C, D> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << ' ' << std::get<3>(t);
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<std::vector<T>> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz; i++) {
        int m = v[i].size();
        for (int j = 0; j < m; j++) dest << v[i][j] << (i != sz - 1 && j == m - 1 ? '\n' : ' ');
    }
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<T> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T, size_t sz>
std::ostream &operator << (std::ostream &dest, const std::array<T, sz> &v) {
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::set<T> &v) {
    for (auto itr = v.begin(); itr != v.end();) {
        dest << *itr;
        itr++;
        if (itr != v.end()) dest << ' ';
    }
    return dest;
}

template<typename T, typename E>
std::ostream &operator << (std::ostream &dest, const std::map<T, E> &v) {
    for (auto itr = v.begin(); itr != v.end(); ) {
        dest << '(' << itr->first << ", " << itr->second << ')';
        itr++;
        if (itr != v.end()) dest << '\n';
    }
    return dest;
}

template<typename T>
std::vector<T> make_vec(size_t sz, T val) { return std::vector<T>(sz, val); }

template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail) {
    return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}

template<typename T>
std::vector<T> read_vec(size_t sz) {
    std::vector<T> v(sz);
    for (int i = 0; i < (int)sz; i++) std::cin >> v[i];
    return v;
}

template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail) {
    auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
    for (int i = 0; i < (int)sz; i++) v[i] = read_vec<T>(tail...);
    return v;
}

template<typename T, size_t size>
auto make_array(T x) { 
    std::array<T, size> res;
    res.fill(x);
    return res;
}

template<typename T, size_t size, size_t size2, size_t... Tail>
auto make_array(T x) {
    std::array<decltype(make_array<T, size2, Tail...>(x)), size> res;
    res.fill(make_array<T, size2, Tail...>(x));
    return res;
}


// x / y以上の最小の整数
ll ceil_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? y - 1 : 0)) / y;
}

// x / y以下の最大の整数
ll floor_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? 0 : -y + 1)) / y;
}

void io_init() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
}



#include <limits>

template<typename T>
struct add_min_function{
  using F = add_min_function<T>;
  T add, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  add_min_function(): add(0), upper(inf){}
  add_min_function(T _add, T _upper): add(_add), upper(_upper){}
  // g(f(x))
  static F merge(const F &f, const F &g){return {f.add + g.add, std::min(g.upper, f.upper + g.add)};}
  T fx(T x){return std::min(x + add, upper);}
  bool operator == (const F &r)const{return add == r.add && upper == r.upper;}
};

// f(x) = min(max(x + a, b), c)
template<typename T>
struct clamp_function{
  T add, lower, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function(): add(0), lower(minf), upper(inf){}
  clamp_function(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper){lower = std::min(_lower, _upper);}
  // g(f(x))
  static clamp_function<T> merge(const clamp_function<T> &f, const clamp_function<T> &g){
    return {f.add + g.add, std::max(g.lower, std::min(f.upper, f.lower) + g.add), std::min(g.upper, std::max(g.lower, f.upper + g.add))};
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  bool operator == (const clamp_function<T> &r)const{return add == r.add && lower == r.lower && upper == r.upper;}
};
// f(x) = min(max(x + a, b), c)
// min部分によって減少した値をスコアとする
template<typename T, typename Tsum>
struct clamp_function_score{
public:
  T add, lower, upper, score_upper;
  Tsum score_sum;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function_score(): add(0), lower(minf), upper(inf), score_upper(inf), score_sum(0){}
  clamp_function_score(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper), score_upper(_upper), score_sum(0){lower = std::min(_lower, _upper);}
private:
  clamp_function_score(T _add, T _lower, T _upper, T _supper, Tsum _ssum): add(_add), lower(_lower), upper(_upper), score_upper(_supper), score_sum(_ssum){}
public:
  // g(f(x))
  static clamp_function_score<T, Tsum> merge(const clamp_function_score<T, Tsum> &f, const clamp_function_score<T, Tsum> &g){
    T _add = f.add + g.add;
    T _lower = std::max(g.lower, std::min(f.upper, f.lower) + g.add);
    T _upper = std::min(g.upper, std::max(g.lower, f.upper + g.add));
    _lower = std::min(_lower, _upper);
    Tsum _ssum = f.score_sum + g.score_sum;
    if(f.lower == f.upper){
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.score_upper + g.add, _ssum};
    }else if(f.lower + g.add >= g.score_upper){
      assert(_lower == _upper);
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.lower + g.add, _ssum};
    }else{
      return {_add, _lower, _upper, std::min(f.score_upper + g.add, g.score_upper), _ssum};
    }
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  Tsum fx_score(T x){
    return score_sum + std::max((T)0, x + add - score_upper);
  }
  bool operator == (const clamp_function_score<T, Tsum> &r)const{return add == r.add && lower == r.lower && upper == r.upper && score_upper == r.score_upper && score_sum == r.score_sum;}
};



template<typename T>
struct prefixsum_min{
  T sum, pmin;
  static prefixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static prefixsum_min<T> merge(prefixsum_min<T> a, prefixsum_min<T> b){
    if(b.pmin == std::numeric_limits<T>::max() / 2) return a;
    return {a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin)};
  }
};
template<typename T>
struct prefixsum_max{
  T sum, pmax;
  static prefixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static prefixsum_max<T> merge(prefixsum_max<T> a, prefixsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min() / 2) return a;
    return {a.sum + b.sum, std::max(a.pmax, a.sum + b.pmax)};
  }
};
template<typename T>
struct suffixsum_min{
  T sum, smin;
  static suffixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static suffixsum_min<T> merge(suffixsum_min<T> a, suffixsum_min<T> b){
    if(a.smin == std::numeric_limits<T>::max() / 2) return b;
    return {a.sum + b.sum, std::min(b.smin, b.sum + a.smin)};
  }
};
template<typename T>
struct suffixsum_max{
  T sum, smax;
  static suffixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static suffixsum_max<T> merge(suffixsum_max<T> a, suffixsum_max<T> b){
    if(a.smax == std::numeric_limits<T>::min() / 2) return b;
    return {a.sum + b.sum, std::max(b.smax, b.sum + a.smax)};
  }
};
template<typename T>
struct substringsum_max{
  T sum, pmax, smax, ssmax; // {区間全体のsum, prefixsumのmax, suffixsumのmax, substringsumのmax}
  static substringsum_max<T> id(){
    return {0, std::numeric_limits<T>::min(), 0, 0};
  }
  static substringsum_max<T> merge(substringsum_max<T> a, substringsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min()) return a;
    if(a.pmax == std::numeric_limits<T>::min()) return b;
    T sum = a.sum + b.sum;
    T pmax = std::max(a.pmax, a.sum + b.pmax);
    T smax = std::max(a.smax + b.sum, b.smax);
    return {sum, pmax, smax, std::max({a.ssmax, b.ssmax, pmax, smax})};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax
struct excess_value{
public:
  int rank, sum, pmin, pmax;
  static constexpr int inf = 1 << 30;
  excess_value(): rank(inf), pmin(inf), pmax(-inf){}
  excess_value(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum){}
private:
  excess_value(int a, int b, int c, int d): rank(a), sum(b), pmin(c), pmax(d){}
public:
  static excess_value merge(excess_value a, excess_value b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), std::max(a.pmax, a.sum + b.pmax)};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax, 接尾辞のmin, 接尾辞のmax
struct excess_value2{
public:
  int rank, sum, pmin, pmax, smin, smax;
  static constexpr int inf = 1 << 30;
  excess_value2(): rank(inf), pmin(inf), pmax(-inf), smin(inf), smax(-inf){}
  excess_value2(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum), smin(sum), smax(sum){}
private:
  excess_value2(int a, int b, int c, int d, int e, int f): rank(a), sum(b), pmin(c), pmax(d), smin(e), smax(f){}
public:
  static excess_value2 merge(excess_value2 a, excess_value2 b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), 
    std::max(a.pmax, a.sum + b.pmax), std::min(a.smin + b.sum, b.smin), std::max(a.smax + b.sum, b.smax)};
  }
};


/*
template<typename T>
struct range_add_chmin_chmax_range_freq {
  private:
    using F = clamp_function<T>;
    struct query {
        int type, l, r;
        F f;
    };
    int N;
    std::vector<T> V;
    std::vector<query> Qs;
  
  public:
    range_add_chmin_chmax_range_freq(int _N) : range_add_chmin_chmax_range_freq(std::vector<T>(_N, 0)) {}
    range_add_chmin_chmax_range_freq(const std::vector<T> &_V) : N(_V.size()), V(_V) {}

    // [l, r)の x <- min(max(x + add, lower), upper)
    void apply(int l, int r, T add, T lower, T upper) {
        assert(lower <= upper);
        Qs.push_back({0, l, r, F{add, lower, upper}});
    }

    // [l, r)のx以上の最小要素
    void lower_bound(int l, int r, T x) {
        Qs.push_back({1, l, r, F{x, x, x}});
    }

    // [l, r)のrx未満の要素数
    void range_freq(int l, int r, T rx) {
        Qs.push_back({2, l, r, F{rx, rx, rx}});
    }

    std::vector<T> solve() {
        int Q = Qs.size(), K = 2 * sqrt(N);
        std::vector<int> Bbegin{0};
        std::vector<F> lz{F{}};
        std::vector<T> B;

        auto propagate = [&]() -> void {
            for (int i = 0; i < (int)Bbegin.size(); i++) {
                if (lz[i] == F()) continue;
                int l = Bbegin[i];
                int r = (i + 1 == Bbegin.size() ? N : Bbegin[i + 1]);
                for (int j = l; j < r; j++) V[j] = lz[i].fx(V[j]);
            }
        };

        auto make_block = [&](int lq, int rq) -> void {
            Bbegin = {0};
            for (int i = lq; i < rq; i++) {
                Bbegin.push_back(Qs[i].l);
                Bbegin.push_back(Qs[i].r);
            }
            std::sort(Bbegin.begin(), Bbegin.end());
            Bbegin.erase(std::unique(Bbegin.begin(), Bbegin.end()), Bbegin.end());
            lz = std::vector<F>(Bbegin.size(), F());
            B = V;
            for (int i = 0; i < Bbegin.size(); i++) {
                int l = Bbegin[i];
                int r = (i + 1 == Bbegin.size() ? N : Bbegin[i + 1]);
                std::sort(B.begin() + l, B.begin() + r);
            }
        };

        std::vector<T> ans;

        for (int i = 0; i < Q; i++) {
            if (i % K == 0) {
                propagate();
                make_block(i, std::min(Q, i + K));
            }
            int l = std::lower_bound(Bbegin.begin(), Bbegin.end(), Qs[i].l) - Bbegin.begin();
            int r = std::lower_bound(Bbegin.begin(), Bbegin.end(), Qs[i].r) - Bbegin.begin();
            if (Qs[i].type == 0) {
                for (int j = l; j < r; j++) {
                    lz[j] = F::merge(lz[j], Qs[i].f);
                }
            } else if (Qs[i].type == 1) {
                T lb = std::numeric_limits<T>::max();
                T x = Qs[i].f.add;
                for (int j = l; j < r; j++) { 
                    T y = x - lz[j].add;
                    auto itr = std::lower_bound(B.begin() + Bbegin[j], B.begin() + Bbegin[j + 1], y);
                    if (itr != B.begin() + Bbegin[j + 1]) {
                        lb = std::min(lb, lz[j].fx(*itr));
                    }
                    if (itr != B.begin() + Bbegin[j] && lz[j].lower >= x) {
                        lb = std::min(lb, lz[j].lower);
                    }
                }
                ans.push_back(lb);
            } else if (Qs[i].type == 2) {
                T cnt = 0, rx = Qs[i].f.add;
                for (int j = l; j < r; j++) { 
                    if (lz[j].lower >= rx) continue;
                    if (lz[j].upper < rx) {
                        cnt += Bbegin[j + 1] - Bbegin[j];
                        continue;
                    }
                    T y = rx - lz[j].add;
                    auto itr = std::lower_bound(B.begin() + Bbegin[j], B.begin() + Bbegin[j + 1], y);
                    cnt += itr - (B.begin() + Bbegin[j]);
                }
                ans.push_back(cnt);
            }
        }
        return ans;
    }
};
*/

template<typename T>
struct range_add_chmin_chmax_range_freq {
  private:
    static constexpr T inf = std::numeric_limits<T>::max();
    static constexpr T minf = std::numeric_limits<T>::min();
    using F = clamp_function<T>;
    int N;
    std::vector<T> V, B;
    std::vector<F> lz;
    std::vector<bool> is_sorted;
    static constexpr int sq = 128;
  
  public:
    range_add_chmin_chmax_range_freq(int _N) : range_add_chmin_chmax_range_freq(std::vector<T>(_N, 0)) {}
    range_add_chmin_chmax_range_freq(const std::vector<T> &_V) : N(_V.size()), V(_V), lz((N + sq - 1) / sq, F()), is_sorted((N + sq - 1) / sq, true) {
        B = V;
        for (int i = 0; i < (N + sq - 1) / sq; i++) {
            int L = i * sq;
            int R = std::min(L + sq, N);
            std::sort(B.begin() + L, B.begin() + R);
        }
    }

    // [l, r)の x <- min(max(x + add, lower), upper)
    void apply(int l, int r, T add, T lower, T upper) {
        assert(l <= r && lower <= upper);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        F f{add, lower, upper};
        if (l < lb * sq) is_sorted[lb - 1] = false;
        if (rb * sq < r) is_sorted[rb] = false;
        if (lb > rb) {
            int L = rb * sq, R = std::min(N, L + sq);
            for (int i = L; i < R; i++) {
                V[i] = lz[rb].fx(V[i]);
                if (l <= i && i < r) V[i] = f.fx(V[i]);
            }
            lz[rb] = F{};
            return;
        }
        if (l < lb * sq) {
            int L = (lb - 1) * sq, R = std::min(N, L + sq);
            for (int i = L; i < l; i++) {
                V[i] = lz[lb - 1].fx(V[i]);
            }
            for (int i = l; i < R; i++) {
                V[i] = f.fx(lz[lb - 1].fx(V[i]));
            }
            lz[lb - 1] = F{};
        }
        if (rb * sq < r) {
            int L = rb * sq, R = std::min(N, L + sq);
            for (int i = L; i < r; i++) {
                V[i] = f.fx(lz[rb].fx(V[i]));
            }
            for (int i = r; i < R; i++) {
                V[i] = lz[rb].fx(V[i]);
            }
            lz[rb] = F{};
        }
        for (int i = lb; i < rb; i++) {
            lz[i] = F::merge(lz[i], f);
        }
    }

    /*
    // [l, r)のx以上の最小要素
    T lower_bound(int l, int r, T x) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        T res = inf;
        if (lb >= rb) {
            for (int i = l; i < r; i++) {
                if (V[i] >= x) res = std::min(res, V[i]);
            }
            return res;
        }
        //
        return res;
    }
    */

    // [l, r)のrx未満の要素数
    int range_freq(int l, int r, T rx) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        int res = 0;
        if (lb > rb) {
            for (int i = l; i < r; i++) {
                T y = lz[rb].fx(V[i]);
                if (y < rx) res++;
            }
            return res;
        }
        for (int i = l; i < lb * sq; i++) {
            T y = lz[lb - 1].fx(V[i]);
            if (y < rx) res++;
        }
        for (int i = rb * sq; i < r; i++) {
            T y = lz[rb].fx(V[i]);
            if (y < rx) res++;
        }
        for (int i = lb; i < rb; i++) {
            if (lz[i].lower >= rx) continue;
            int L = i * sq, R = std::min(N, L + sq);
            if (lz[i].upper < rx) {
                res += R - L;
                continue;
            }
            if (!is_sorted[i]) {
                for (int j = L; j < R; j++) B[j] = V[j];
                std::sort(B.begin() + L, B.begin() + R);
                is_sorted[i] = true;
            }
            res += std::lower_bound(B.begin() + L, B.begin() + R, rx - lz[i].add) - (B.begin() + L);
        }
        return res;
    }
    /*

    // [l, r)のrx未満の要素の和
    T range_freq_sum(int l, int r, T rx) {
        assert(l <= r);
        int lb = (l + sq - 1) / sq, rb = r / sq;
        T res = 0;
        if (lb >= rb) {
            for (int i = l; i < r; i++) {
                if (V[i] < rx) res += V[i];
            }
            return res;
        }
        //
        return res;
    }
    */
};

int main() {
    io_init();
    int N, Q;
    std::cin >> N >> Q;
    auto A = read_vec<ll>(N);
    range_add_chmin_chmax_range_freq<ll> F(A);

    static constexpr ll inf = 1LL << 60, minf = -inf;
    for (int i = 0; i < Q; i++) {
        int t, l, r;
        ll x;
        std::cin >> t >> l >> r >> x;
        l--;
        if (t == 1) {
            F.apply(l, r, 0, minf, x);
        } else if (t == 2) {
            F.apply(l, r, 0, x, inf);
        } else if (t == 3) {
            F.apply(l, r, x, minf, inf);
        } else {
            ll y;
            std::cin >> y;
            ll ans = F.range_freq(l, r, y + 1) - F.range_freq(l, r, x);
            std::cout << ans << '\n';
        }
    }
}
accuracy: 1
time_ms: 1000
memory_kb: 5468
final_rank: 5

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#include <thread>
#include <chrono>
#define allof(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
using namespace std;

template<typename F, typename S>
std::ostream &operator << (std::ostream &dest, const std::pair<F, S> &p) {
    dest << p.first << ' ' << p.second;
    return dest;
}

template<typename A, typename B>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t);
    return dest;
}

template<typename A, typename B, typename C>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t);
    return dest;
}

template<typename A, typename B, typename C, typename D>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C, D> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << ' ' << std::get<3>(t);
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<std::vector<T>> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz; i++) {
        int m = v[i].size();
        for (int j = 0; j < m; j++) dest << v[i][j] << (i != sz - 1 && j == m - 1 ? '\n' : ' ');
    }
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<T> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T, size_t sz>
std::ostream &operator << (std::ostream &dest, const std::array<T, sz> &v) {
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::set<T> &v) {
    for (auto itr = v.begin(); itr != v.end();) {
        dest << *itr;
        itr++;
        if (itr != v.end()) dest << ' ';
    }
    return dest;
}

template<typename T, typename E>
std::ostream &operator << (std::ostream &dest, const std::map<T, E> &v) {
    for (auto itr = v.begin(); itr != v.end(); ) {
        dest << '(' << itr->first << ", " << itr->second << ')';
        itr++;
        if (itr != v.end()) dest << '\n';
    }
    return dest;
}

template<typename T>
std::vector<T> make_vec(size_t sz, T val) { return std::vector<T>(sz, val); }

template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail) {
    return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}

template<typename T>
std::vector<T> read_vec(size_t sz) {
    std::vector<T> v(sz);
    for (int i = 0; i < (int)sz; i++) std::cin >> v[i];
    return v;
}

template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail) {
    auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
    for (int i = 0; i < (int)sz; i++) v[i] = read_vec<T>(tail...);
    return v;
}

template<typename T, size_t size>
auto make_array(T x) { 
    std::array<T, size> res;
    res.fill(x);
    return res;
}

template<typename T, size_t size, size_t size2, size_t... Tail>
auto make_array(T x) {
    std::array<decltype(make_array<T, size2, Tail...>(x)), size> res;
    res.fill(make_array<T, size2, Tail...>(x));
    return res;
}


// x / y以上の最小の整数
ll ceil_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? y - 1 : 0)) / y;
}

// x / y以下の最大の整数
ll floor_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? 0 : -y + 1)) / y;
}

void io_init() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
}



#include <limits>

template<typename T>
struct add_min_function{
  using F = add_min_function<T>;
  T add, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  add_min_function(): add(0), upper(inf){}
  add_min_function(T _add, T _upper): add(_add), upper(_upper){}
  // g(f(x))
  static F merge(const F &f, const F &g){return {f.add + g.add, std::min(g.upper, f.upper + g.add)};}
  T fx(T x){return std::min(x + add, upper);}
  bool operator == (const F &r)const{return add == r.add && upper == r.upper;}
};

// f(x) = min(max(x + a, b), c)
template<typename T>
struct clamp_function{
  T add, lower, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function(): add(0), lower(minf), upper(inf){}
  clamp_function(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper){lower = std::min(_lower, _upper);}
  // g(f(x))
  static clamp_function<T> merge(const clamp_function<T> &f, const clamp_function<T> &g){
    return {f.add + g.add, std::max(g.lower, std::min(f.upper, f.lower) + g.add), std::min(g.upper, std::max(g.lower, f.upper + g.add))};
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  bool operator == (const clamp_function<T> &r)const{return add == r.add && lower == r.lower && upper == r.upper;}
};
// f(x) = min(max(x + a, b), c)
// min部分によって減少した値をスコアとする
template<typename T, typename Tsum>
struct clamp_function_score{
public:
  T add, lower, upper, score_upper;
  Tsum score_sum;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function_score(): add(0), lower(minf), upper(inf), score_upper(inf), score_sum(0){}
  clamp_function_score(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper), score_upper(_upper), score_sum(0){lower = std::min(_lower, _upper);}
private:
  clamp_function_score(T _add, T _lower, T _upper, T _supper, Tsum _ssum): add(_add), lower(_lower), upper(_upper), score_upper(_supper), score_sum(_ssum){}
public:
  // g(f(x))
  static clamp_function_score<T, Tsum> merge(const clamp_function_score<T, Tsum> &f, const clamp_function_score<T, Tsum> &g){
    T _add = f.add + g.add;
    T _lower = std::max(g.lower, std::min(f.upper, f.lower) + g.add);
    T _upper = std::min(g.upper, std::max(g.lower, f.upper + g.add));
    _lower = std::min(_lower, _upper);
    Tsum _ssum = f.score_sum + g.score_sum;
    if(f.lower == f.upper){
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.score_upper + g.add, _ssum};
    }else if(f.lower + g.add >= g.score_upper){
      assert(_lower == _upper);
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.lower + g.add, _ssum};
    }else{
      return {_add, _lower, _upper, std::min(f.score_upper + g.add, g.score_upper), _ssum};
    }
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  Tsum fx_score(T x){
    return score_sum + std::max((T)0, x + add - score_upper);
  }
  bool operator == (const clamp_function_score<T, Tsum> &r)const{return add == r.add && lower == r.lower && upper == r.upper && score_upper == r.score_upper && score_sum == r.score_sum;}
};



template<typename T>
struct prefixsum_min{
  T sum, pmin;
  static prefixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static prefixsum_min<T> merge(prefixsum_min<T> a, prefixsum_min<T> b){
    if(b.pmin == std::numeric_limits<T>::max() / 2) return a;
    return {a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin)};
  }
};
template<typename T>
struct prefixsum_max{
  T sum, pmax;
  static prefixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static prefixsum_max<T> merge(prefixsum_max<T> a, prefixsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min() / 2) return a;
    return {a.sum + b.sum, std::max(a.pmax, a.sum + b.pmax)};
  }
};
template<typename T>
struct suffixsum_min{
  T sum, smin;
  static suffixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static suffixsum_min<T> merge(suffixsum_min<T> a, suffixsum_min<T> b){
    if(a.smin == std::numeric_limits<T>::max() / 2) return b;
    return {a.sum + b.sum, std::min(b.smin, b.sum + a.smin)};
  }
};
template<typename T>
struct suffixsum_max{
  T sum, smax;
  static suffixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static suffixsum_max<T> merge(suffixsum_max<T> a, suffixsum_max<T> b){
    if(a.smax == std::numeric_limits<T>::min() / 2) return b;
    return {a.sum + b.sum, std::max(b.smax, b.sum + a.smax)};
  }
};
template<typename T>
struct substringsum_max{
  T sum, pmax, smax, ssmax; // {区間全体のsum, prefixsumのmax, suffixsumのmax, substringsumのmax}
  static substringsum_max<T> id(){
    return {0, std::numeric_limits<T>::min(), 0, 0};
  }
  static substringsum_max<T> merge(substringsum_max<T> a, substringsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min()) return a;
    if(a.pmax == std::numeric_limits<T>::min()) return b;
    T sum = a.sum + b.sum;
    T pmax = std::max(a.pmax, a.sum + b.pmax);
    T smax = std::max(a.smax + b.sum, b.smax);
    return {sum, pmax, smax, std::max({a.ssmax, b.ssmax, pmax, smax})};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax
struct excess_value{
public:
  int rank, sum, pmin, pmax;
  static constexpr int inf = 1 << 30;
  excess_value(): rank(inf), pmin(inf), pmax(-inf){}
  excess_value(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum){}
private:
  excess_value(int a, int b, int c, int d): rank(a), sum(b), pmin(c), pmax(d){}
public:
  static excess_value merge(excess_value a, excess_value b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), std::max(a.pmax, a.sum + b.pmax)};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax, 接尾辞のmin, 接尾辞のmax
struct excess_value2{
public:
  int rank, sum, pmin, pmax, smin, smax;
  static constexpr int inf = 1 << 30;
  excess_value2(): rank(inf), pmin(inf), pmax(-inf), smin(inf), smax(-inf){}
  excess_value2(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum), smin(sum), smax(sum){}
private:
  excess_value2(int a, int b, int c, int d, int e, int f): rank(a), sum(b), pmin(c), pmax(d), smin(e), smax(f){}
public:
  static excess_value2 merge(excess_value2 a, excess_value2 b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), 
    std::max(a.pmax, a.sum + b.pmax), std::min(a.smin + b.sum, b.smin), std::max(a.smax + b.sum, b.smax)};
  }
};


template<typename T>
struct range_add_chmin_chmax_range_freq {
  private:
    using F = clamp_function<T>;
    struct query {
        int type, l, r;
        F f;
    };
    int N;
    std::vector<T> V;
    std::vector<query> Qs;
  
  public:
    range_add_chmin_chmax_range_freq(int _N) : range_add_chmin_chmax_range_freq(std::vector<T>(_N, 0)) {}
    range_add_chmin_chmax_range_freq(const std::vector<T> &_V) : N(_V.size()), V(_V) {}

    // [l, r)の x <- min(max(x + add, lower), upper)
    void apply(int l, int r, T add, T lower, T upper) {
        assert(lower <= upper);
        Qs.push_back({0, l, r, F{add, lower, upper}});
    }

    // [l, r)のx以上の最小要素
    void lower_bound(int l, int r, T x) {
        Qs.push_back({1, l, r, F{x, x, x}});
    }

    // [l, r)のrx未満の要素数
    void range_freq(int l, int r, T rx) {
        Qs.push_back({2, l, r, F{rx, rx, rx}});
    }

    /*
    // [l, r)のrx未満の要素の和
    void range_freq_sum(int l, int r, T rx) {
        //
    }
    */

    std::vector<T> solve() {
        int Q = Qs.size(), K = 2 * sqrt(N);
        std::vector<int> Bbegin{0};
        std::vector<F> lz{F{}};
        std::vector<T> B;

        auto propagate = [&]() -> void {
            for (int i = 0; i < (int)Bbegin.size(); i++) {
                if (lz[i] == F()) continue;
                int l = Bbegin[i];
                int r = (i + 1 == Bbegin.size() ? N : Bbegin[i + 1]);
                for (int j = l; j < r; j++) V[j] = lz[i].fx(V[j]);
            }
        };

        auto make_block = [&](int lq, int rq) -> void {
            Bbegin = {0};
            for (int i = lq; i < rq; i++) {
                Bbegin.push_back(Qs[i].l);
                Bbegin.push_back(Qs[i].r);
            }
            std::sort(Bbegin.begin(), Bbegin.end());
            Bbegin.erase(std::unique(Bbegin.begin(), Bbegin.end()), Bbegin.end());
            lz = std::vector<F>(Bbegin.size(), F());
            B = V;
            for (int i = 0; i < Bbegin.size(); i++) {
                int l = Bbegin[i];
                int r = (i + 1 == Bbegin.size() ? N : Bbegin[i + 1]);
                std::sort(B.begin() + l, B.begin() + r);
            }
        };

        std::vector<T> ans;

        for (int i = 0; i < Q; i++) {
            if (i % K == 0) {
                propagate();
                make_block(i, std::min(Q, i + K));
            }
            int l = std::lower_bound(Bbegin.begin(), Bbegin.end(), Qs[i].l) - Bbegin.begin();
            int r = std::lower_bound(Bbegin.begin(), Bbegin.end(), Qs[i].r) - Bbegin.begin();
            if (Qs[i].type == 0) {
                for (int j = l; j < r; j++) {
                    lz[j] = F::merge(lz[j], Qs[i].f);
                }
            } else if (Qs[i].type == 1) {
                T lb = std::numeric_limits<T>::max();
                T x = Qs[i].f.add;
                for (int j = l; j < r; j++) { 
                    T y = x - lz[j].add;
                    auto itr = std::lower_bound(B.begin() + Bbegin[j], B.begin() + Bbegin[j + 1], y);
                    if (itr != B.begin() + Bbegin[j + 1]) {
                        lb = std::min(lb, lz[j].fx(*itr));
                    }
                    if (itr != B.begin() + Bbegin[j] && lz[j].lower >= x) {
                        lb = std::min(lb, lz[j].lower);
                    }
                }
                ans.push_back(lb);
            } else if (Qs[i].type == 2) {
                T cnt = 0, rx = Qs[i].f.add;
                for (int j = l; j < r; j++) { 
                    if (lz[j].lower >= rx) continue;
                    if (lz[j].upper < rx) {
                        cnt += Bbegin[j + 1] - Bbegin[j];
                        continue;
                    }
                    T y = rx - lz[j].add;
                    auto itr = std::lower_bound(B.begin() + Bbegin[j], B.begin() + Bbegin[j + 1], y);
                    cnt += itr - (B.begin() + Bbegin[j]);
                }
                ans.push_back(cnt);
            }
        }
        return ans;
    }
};

int main() {
    io_init();
    int N, Q;
    std::cin >> N >> Q;
    auto A = read_vec<ll>(N);
    range_add_chmin_chmax_range_freq<ll> F(A);

    static constexpr ll inf = 1LL << 60, minf = -inf;
    for (int i = 0; i < Q; i++) {
        int t, l, r;
        ll x;
        std::cin >> t >> l >> r >> x;
        l--;
        if (t == 1) {
            F.apply(l, r, 0, minf, x);
        } else if (t == 2) {
            F.apply(l, r, 0, x, inf);
        } else if (t == 3) {
            F.apply(l, r, x, minf, inf);
        } else {
            ll y;
            std::cin >> y;
            F.range_freq(l, r, x);
            F.range_freq(l, r, y + 1);
        }
    }

    auto ans = F.solve();

    for (int i = 0; i < ans.size(); i += 2) {
        std::cout << ans[i + 1] - ans[i] << '\n';
    }

}
accuracy: 1
time_ms: 970
memory_kb: 11908
final_rank: 15

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#include <thread>
#include <chrono>
#define allof(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
using namespace std;

template<typename F, typename S>
std::ostream &operator << (std::ostream &dest, const std::pair<F, S> &p) {
    dest << p.first << ' ' << p.second;
    return dest;
}

template<typename A, typename B>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t);
    return dest;
}

template<typename A, typename B, typename C>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t);
    return dest;
}

template<typename A, typename B, typename C, typename D>
std::ostream &operator << (std::ostream &dest, const std::tuple<A, B, C, D> &t) {
    dest << std::get<0>(t) << ' ' << std::get<1>(t) << ' ' << std::get<2>(t) << ' ' << std::get<3>(t);
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<std::vector<T>> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz; i++) {
        int m = v[i].size();
        for (int j = 0; j < m; j++) dest << v[i][j] << (i != sz - 1 && j == m - 1 ? '\n' : ' ');
    }
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::vector<T> &v) {
    int sz = v.size();
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T, size_t sz>
std::ostream &operator << (std::ostream &dest, const std::array<T, sz> &v) {
    if (!sz) return dest;
    for (int i = 0; i < sz - 1; i++) dest << v[i] << ' ';
    dest << v[sz - 1];
    return dest;
}

template<typename T>
std::ostream &operator << (std::ostream &dest, const std::set<T> &v) {
    for (auto itr = v.begin(); itr != v.end();) {
        dest << *itr;
        itr++;
        if (itr != v.end()) dest << ' ';
    }
    return dest;
}

template<typename T, typename E>
std::ostream &operator << (std::ostream &dest, const std::map<T, E> &v) {
    for (auto itr = v.begin(); itr != v.end(); ) {
        dest << '(' << itr->first << ", " << itr->second << ')';
        itr++;
        if (itr != v.end()) dest << '\n';
    }
    return dest;
}

template<typename T>
std::vector<T> make_vec(size_t sz, T val) { return std::vector<T>(sz, val); }

template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail) {
    return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}

template<typename T>
std::vector<T> read_vec(size_t sz) {
    std::vector<T> v(sz);
    for (int i = 0; i < (int)sz; i++) std::cin >> v[i];
    return v;
}

template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail) {
    auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
    for (int i = 0; i < (int)sz; i++) v[i] = read_vec<T>(tail...);
    return v;
}

template<typename T, size_t size>
auto make_array(T x) { 
    std::array<T, size> res;
    res.fill(x);
    return res;
}

template<typename T, size_t size, size_t size2, size_t... Tail>
auto make_array(T x) {
    std::array<decltype(make_array<T, size2, Tail...>(x)), size> res;
    res.fill(make_array<T, size2, Tail...>(x));
    return res;
}


// x / y以上の最小の整数
ll ceil_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? y - 1 : 0)) / y;
}

// x / y以下の最大の整数
ll floor_div(ll x, ll y) {
    assert(y > 0);
    return (x + (x > 0 ? 0 : -y + 1)) / y;
}

void io_init() {
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
}



#include <limits>

template<typename T>
struct add_min_function{
  using F = add_min_function<T>;
  T add, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  add_min_function(): add(0), upper(inf){}
  add_min_function(T _add, T _upper): add(_add), upper(_upper){}
  // g(f(x))
  static F merge(const F &f, const F &g){return {f.add + g.add, std::min(g.upper, f.upper + g.add)};}
  T fx(T x){return std::min(x + add, upper);}
  bool operator == (const F &r)const{return add == r.add && upper == r.upper;}
};

// f(x) = min(max(x + a, b), c)
template<typename T>
struct clamp_function{
  T add, lower, upper;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function(): add(0), lower(minf), upper(inf){}
  clamp_function(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper){lower = std::min(_lower, _upper);}
  // g(f(x))
  static clamp_function<T> merge(const clamp_function<T> &f, const clamp_function<T> &g){
    return {f.add + g.add, std::max(g.lower, std::min(f.upper, f.lower) + g.add), std::min(g.upper, std::max(g.lower, f.upper + g.add))};
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  bool operator == (const clamp_function<T> &r)const{return add == r.add && lower == r.lower && upper == r.upper;}
};
// f(x) = min(max(x + a, b), c)
// min部分によって減少した値をスコアとする
template<typename T, typename Tsum>
struct clamp_function_score{
public:
  T add, lower, upper, score_upper;
  Tsum score_sum;
  static constexpr T inf = std::numeric_limits<T>::max() / 2;
  static constexpr T minf = std::numeric_limits<T>::min() / 2;
  clamp_function_score(): add(0), lower(minf), upper(inf), score_upper(inf), score_sum(0){}
  clamp_function_score(T _add, T _lower, T _upper): add(_add), lower(_lower), upper(_upper), score_upper(_upper), score_sum(0){lower = std::min(_lower, _upper);}
private:
  clamp_function_score(T _add, T _lower, T _upper, T _supper, Tsum _ssum): add(_add), lower(_lower), upper(_upper), score_upper(_supper), score_sum(_ssum){}
public:
  // g(f(x))
  static clamp_function_score<T, Tsum> merge(const clamp_function_score<T, Tsum> &f, const clamp_function_score<T, Tsum> &g){
    T _add = f.add + g.add;
    T _lower = std::max(g.lower, std::min(f.upper, f.lower) + g.add);
    T _upper = std::min(g.upper, std::max(g.lower, f.upper + g.add));
    _lower = std::min(_lower, _upper);
    Tsum _ssum = f.score_sum + g.score_sum;
    if(f.lower == f.upper){
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.score_upper + g.add, _ssum};
    }else if(f.lower + g.add >= g.score_upper){
      assert(_lower == _upper);
      _ssum += std::max((T)0, f.lower + g.add - g.score_upper);
      return {_add, _lower, _upper, f.lower + g.add, _ssum};
    }else{
      return {_add, _lower, _upper, std::min(f.score_upper + g.add, g.score_upper), _ssum};
    }
  }
  T fx(T x){
    return std::min(std::max(x + add, lower), upper);
  }
  Tsum fx_score(T x){
    return score_sum + std::max((T)0, x + add - score_upper);
  }
  bool operator == (const clamp_function_score<T, Tsum> &r)const{return add == r.add && lower == r.lower && upper == r.upper && score_upper == r.score_upper && score_sum == r.score_sum;}
};



template<typename T>
struct prefixsum_min{
  T sum, pmin;
  static prefixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static prefixsum_min<T> merge(prefixsum_min<T> a, prefixsum_min<T> b){
    if(b.pmin == std::numeric_limits<T>::max() / 2) return a;
    return {a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin)};
  }
};
template<typename T>
struct prefixsum_max{
  T sum, pmax;
  static prefixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static prefixsum_max<T> merge(prefixsum_max<T> a, prefixsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min() / 2) return a;
    return {a.sum + b.sum, std::max(a.pmax, a.sum + b.pmax)};
  }
};
template<typename T>
struct suffixsum_min{
  T sum, smin;
  static suffixsum_min<T> id(){
    return {0, std::numeric_limits<T>::max() / 2};
  }
  static suffixsum_min<T> merge(suffixsum_min<T> a, suffixsum_min<T> b){
    if(a.smin == std::numeric_limits<T>::max() / 2) return b;
    return {a.sum + b.sum, std::min(b.smin, b.sum + a.smin)};
  }
};
template<typename T>
struct suffixsum_max{
  T sum, smax;
  static suffixsum_max<T> id(){
    return {0, std::numeric_limits<T>::min() / 2};
  }
  static suffixsum_max<T> merge(suffixsum_max<T> a, suffixsum_max<T> b){
    if(a.smax == std::numeric_limits<T>::min() / 2) return b;
    return {a.sum + b.sum, std::max(b.smax, b.sum + a.smax)};
  }
};
template<typename T>
struct substringsum_max{
  T sum, pmax, smax, ssmax; // {区間全体のsum, prefixsumのmax, suffixsumのmax, substringsumのmax}
  static substringsum_max<T> id(){
    return {0, std::numeric_limits<T>::min(), 0, 0};
  }
  static substringsum_max<T> merge(substringsum_max<T> a, substringsum_max<T> b){
    if(b.pmax == std::numeric_limits<T>::min()) return a;
    if(a.pmax == std::numeric_limits<T>::min()) return b;
    T sum = a.sum + b.sum;
    T pmax = std::max(a.pmax, a.sum + b.pmax);
    T smax = std::max(a.smax + b.sum, b.smax);
    return {sum, pmax, smax, std::max({a.ssmax, b.ssmax, pmax, smax})};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax
struct excess_value{
public:
  int rank, sum, pmin, pmax;
  static constexpr int inf = 1 << 30;
  excess_value(): rank(inf), pmin(inf), pmax(-inf){}
  excess_value(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum){}
private:
  excess_value(int a, int b, int c, int d): rank(a), sum(b), pmin(c), pmax(d){}
public:
  static excess_value merge(excess_value a, excess_value b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), std::max(a.pmax, a.sum + b.pmax)};
  }
};
// 01列の0を-1として扱う
// 1の数, 合計, 接頭辞のmin, 接頭辞のmax, 接尾辞のmin, 接尾辞のmax
struct excess_value2{
public:
  int rank, sum, pmin, pmax, smin, smax;
  static constexpr int inf = 1 << 30;
  excess_value2(): rank(inf), pmin(inf), pmax(-inf), smin(inf), smax(-inf){}
  excess_value2(bool f): rank(f), sum(f ? 1 : -1), pmin(sum), pmax(sum), smin(sum), smax(sum){}
private:
  excess_value2(int a, int b, int c, int d, int e, int f): rank(a), sum(b), pmin(c), pmax(d), smin(e), smax(f){}
public:
  static excess_value2 merge(excess_value2 a, excess_value2 b){
    if(a.rank == inf) return b;
    if(b.rank == inf) return a;
    return {a.rank + b.rank, a.sum + b.sum, std::min(a.pmin, a.sum + b.pmin), 
    std::max(a.pmax, a.sum + b.pmax), std::min(a.smin + b.sum, b.smin), std::max(a.smax + b.sum, b.smax)};
  }
};


template<typename T>
struct range_add_chmin_chmax_range_freq {
  private:
    using F = clamp_function<T>;
    struct query {
        int type, l, r;
        F f;
    };
    int N;
    std::vector<T> V;
    std::vector<query> Qs;
  
  public:
    range_add_chmin_chmax_range_freq(int _N) : range_add_chmin_chmax_range_freq(std::vector<T>(_N, 0)) {}
    range_add_chmin_chmax_range_freq(const std::vector<T> &_V) : N(_V.size()), V(_V) {}

    // [l, r)の x <- min(max(x + add, lower), upper)
    void apply(int l, int r, T add, T lower, T upper) {
        assert(lower <= upper);
        Qs.push_back({0, l, r, F{add, lower, upper}});
    }

    // [l, r)のx以上の最小要素
    void lower_bound(int l, int r, T x) {
        Qs.push_back({1, l, r, F{x, x, x}});
    }

    // [l, r)のrx未満の要素数
    void range_freq(int l, int r, T rx) {
        Qs.push_back({2, l, r, F{rx, rx, rx}});
    }

    /*
    // [l, r)のrx未満の要素の和
    void range_freq_sum(int l, int r, T rx) {
        //
    }
    */

    std::vector<T> solve() {
        int Q = Qs.size(), K = 2 * sqrt(N);
        std::vector<int> Bbegin{0};
        std::vector<F> lz{F{}};
        std::vector<T> B;

        auto propagate = [&]() -> void {
            for (int i = 0; i < (int)Bbegin.size(); i++) {
                if (lz[i] == F()) continue;
                int l = Bbegin[i];
                int r = (i + 1 == Bbegin.size() ? N : Bbegin[i + 1]);
                for (int j = l; j < r; j++) V[j] = lz[i].fx(V[j]);
            }
        };

        auto make_block = [&](int lq, int rq) -> void {
            Bbegin = {0};
            for (int i = lq; i < rq; i++) {
                Bbegin.push_back(Qs[i].l);
                Bbegin.push_back(Qs[i].r);
            }
            std::sort(Bbegin.begin(), Bbegin.end());
            Bbegin.erase(std::unique(Bbegin.begin(), Bbegin.end()), Bbegin.end());
            lz = std::vector<F>(Bbegin.size(), F());
            B = V;
            for (int i = 0; i < Bbegin.size(); i++) {
                int l = Bbegin[i];
                int r = (i + 1 == Bbegin.size() ? N : Bbegin[i + 1]);
                std::sort(B.begin() + l, B.begin() + r);
            }
        };

        std::vector<T> ans;

        for (int i = 0; i < Q; i++) {
            if (i % K == 0) {
                propagate();
                make_block(i, std::min(Q, i + K));
            }
            int l = std::lower_bound(Bbegin.begin(), Bbegin.end(), Qs[i].l) - Bbegin.begin();
            int r = std::lower_bound(Bbegin.begin(), Bbegin.end(), Qs[i].r) - Bbegin.begin();
            if (Qs[i].type == 0) {
                for (int j = l; j < r; j++) {
                    lz[j] = F::merge(lz[j], Qs[i].f);
                }
            } else if (Qs[i].type == 1) {
                T lb = std::numeric_limits<T>::max();
                T x = Qs[i].f.add;
                for (int j = l; j < r; j++) { 
                    T y = x - lz[j].add;
                    auto itr = std::lower_bound(B.begin() + Bbegin[j], B.begin() + Bbegin[j + 1], y);
                    if (itr != B.begin() + Bbegin[j + 1]) {
                        lb = std::min(lb, lz[j].fx(*itr));
                    }
                    if (itr != B.begin() + Bbegin[j] && lz[j].lower >= x) {
                        lb = std::min(lb, lz[j].lower);
                    }
                }
                ans.push_back(lb);
            } else if (Qs[i].type == 2) {
                T cnt = 0, rx = Qs[i].f.add;
                for (int j = l; j < r; j++) { 
                    if (lz[j].lower >= rx) continue;
                    if (lz[j].upper < rx) {
                        cnt += Bbegin[j + 1] - Bbegin[j];
                        continue;
                    }
                    T y = rx - lz[j].add;
                    auto itr = std::lower_bound(B.begin() + Bbegin[j], B.begin() + Bbegin[j + 1], y);
                    cnt += itr - (B.begin() + Bbegin[j]);
                }
                ans.push_back(cnt);
            }
        }
        return ans;
    }
};

int main() {
    io_init();
    int N, Q;
    std::cin >> N >> Q;
    auto A = read_vec<ll>(N);
    range_add_chmin_chmax_range_freq<ll> F(A);

    static constexpr ll inf = 1LL << 60, minf = -inf;
    for (int i = 0; i < Q; i++) {
        int t, l, r, x;
        std::cin >> t >> l >> r >> x;
        l--;
        if (t == 1) {
            F.apply(l, r, 0, minf, x);
        } else if (t == 2) {
            F.apply(l, r, 0, x, inf);
        } else if (t == 3) {
            F.apply(l, r, x, minf, inf);
        } else {
            int y;
            std::cin >> y;
            F.range_freq(l, r, x);
            F.range_freq(l, r, y + 1);
        }
    }

    auto ans = F.solve();

    for (int i = 0; i < ans.size(); i += 2) {
        std::cout << ans[i + 1] - ans[i] << '\n';
    }

}
accuracy: 0.09523809523809523
time_ms: 350
memory_kb: 8288
final_rank: 19

code_snippet: #pragma region Macros
 
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,fma,abm,mmx,avx,avx2")
 
#include <bits/extc++.h>
// #include <atcoder/all>
// using namespace atcoder;
using namespace std;
using namespace __gnu_pbds;
 
// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// namespace mp = boost::multiprecision;
// using Bint = mp::cpp_int;
// using Bdouble = mp::number<mp::cpp_dec_float<256>>;
// Bdouble Beps = 0.00000000000000000000000000000001; // 1e-32
// const bool equals(Bdouble a, Bdouble b) { return mp::fabs(a - b) < Beps; }
 
#define pb emplace_back
#define int ll
#define endl '\n'
// #define unordered_map<int, int> gp_hash_table<int, int, custom_hash> 
 
#define sqrt __builtin_sqrtl
#define cbrt __builtin_cbrtl
#define hypot __builtin_hypotl
 
#define next asdnext
#define prev asdprev
 
using ll = long long;
using ld = long double;
const ld PI = acosl(-1);
const int INF = 1 << 30;
const ll INFL = 1LL << 61;
const int MOD = 998244353;
// const int MOD = 1000000007;
 
const ld EPS = 1e-10;
const bool equals(ld a, ld b) { return fabs((a) - (b)) < EPS; }
 
const vector<int> dx = {0, 1, 0, -1, 1, 1, -1, -1}; // → ↓ ← ↑ ↘ ↙ ↖ ↗
const vector<int> dy = {1, 0, -1, 0, 1, -1, -1, 1};
 
#define EC int
struct Edge {
    int from, to;
    EC cost;
    Edge() : from(-1), to(-1), cost(-1) {}
    Edge(int to, EC cost) : to(to), cost(cost) {}
    Edge(int from, int to, EC cost) : from(from), to(to), cost(cost) {}
    bool operator ==(const Edge& e) {
        return this->from == e.from && this->to == e.to && this->cost == e.cost;
    }
    bool operator !=(const Edge& e) {
        return this->from != e.from or this->to != e.to or this->cost != e.cost;
    }
    bool operator <(const Edge& e) { return this->cost < e.cost; }
    bool operator >(const Edge& e) { return this->cost > e.cost; }
};
 
chrono::system_clock::time_point start;
__attribute__((constructor))
void constructor() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(10);
    start = chrono::system_clock::now();
}
 
random_device seed_gen;
mt19937_64 rng(seed_gen());
uniform_int_distribution<int> dist_x(0, 1e9);
struct RNG {
    unsigned Int(unsigned l, unsigned r) {
        return dist_x(rng) % (r - l + 1) + l;
    }
    ld Double() {
        return ld(dist_x(rng)) / 1e9;
    }
} rnd;
 
using i64 = ll;
// using i64 = uint64_t;
// bit演算, x==0の場合は例外処理した方がよさそう. 区間は [l, r)
i64 lrmask(i64 l, i64 r) { return (1LL << r) - (1LL << l); }
i64 sub_bit(i64 x, i64 l, i64 r) { i64 b = x & ((1LL << r) - (1LL << l)); return b >> l; } // r溢れ可
i64 bit_width(i64 x) { return 64 - __builtin_clzll(x) + (x == 0); }
 
i64 popcount(i64 x) { return __builtin_popcountll(x); }
i64 popcount(i64 x, i64 l, i64 r) { return __builtin_popcountll(sub_bit(x, l, r)); }
i64 unpopcount(i64 x) { return bit_width(x) - __builtin_popcountll(x); }
i64 unpopcount(i64 x, i64 l, i64 r) { return r - l - __builtin_popcountll(sub_bit(x, l, r)); }
bool is_pow2(i64 x) { return __builtin_popcountll(x) == 1; } // xが負のときは常にfalse
bool is_pow4(i64 x) { return __builtin_popcount(x) == 1 && __builtin_ctz(x) % 2 == 0; }
 
i64 top_bit(i64 x) { return 63 - __builtin_clzll(x);} // 2^kの位 (x > 0)
i64 bot_bit(i64 x) { return __builtin_ctzll(x);} // 2^kの位 (x > 0)
// i64 next_bit(i64 x, i64 k) { return 0; }
// i64 prev_bit(i64 x, i64 k) { return 0; }
// i64 kth_bit(i64 x, i64 k) { return 0; }
i64 MSB(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // mask
i64 LSB(i64 x) { return (x & -x); } // mask
 
i64 countl_zero(i64 x) { return __builtin_clzll(x); }
i64 countl_one(i64 x) {
    i64 ret = 0, k = 63 - __builtin_clzll(x);
    while (k != -1 && (x & (1LL << k))) { k--; ret++; }
    return ret;
}
i64 countr_zero(i64 x) { return __builtin_ctzll(x); } // x==0のとき64が返ることに注意
i64 countr_one(i64 x) { i64 ret = 0; while (x & 1) { x >>= 1; ret++; } return ret; }
 
i64 floor_log2(i64 x) { if (x == 0) return 0; return 63 - __builtin_clzll(x); }
i64 bit_floor(i64 x) { if (x == 0) return 0; return 1LL << (63 - __builtin_clzll(x)); } // MSBと同じ
i64 ceil_log2(i64 x) { if (x == 0) return 0; return 64 - __builtin_clzll(x - 1); }
i64 bit_ceil(i64 x) { if (x == 0) return 0; return 1LL << (64 - __builtin_clzll(x - 1)); }
 
i64 rotl(i64 x, i64 k) { // 有効bit内でrotate. オーバーフロー注意
    i64 w = bit_width(x); k %= w;
    return ((x << k) | (x >> (w - k))) & ((1LL << w) - 1);
}
// i64 rotl(i64 x, i64 l, i64 m, i64 r) {}
i64 rotr(i64 x, i64 k) {
    i64 w = bit_width(x); k %= w;
    return ((x >> k) | (x << (w - k))) & ((1LL << w) - 1);
}
// i64 rotr(i64 x, i64 l, i64 m, i64 r) {}
i64 bit_reverse(i64 x) { // 有効bit内で左右反転
    i64 r = 0, w = bit_width(x);
    for (i64 i = 0; i < w; i++) r |= ((x >> i) & 1) << (w - i - 1);
    return r;
}
// i64 bit_reverse(i64 x, i64 l, i64 r) { return 0; }
 
bool is_palindrome(i64 x) { return x == bit_reverse(x); }
bool is_palindrome(i64 x, i64 l, i64 r) { i64 b = sub_bit(x, l, r); return b == bit_reverse(b); }
i64 concat(i64 a, i64 b) { return (a << bit_width(b)) | b; } // オーバーフロー注意
i64 erase(i64 x, i64 l, i64 r) { return x>>r<<l | x&(1LL<<l - 1); } // [l, r) をカット
 
i64 hamming(i64 a, i64 b) { return __builtin_popcountll(a ^ b); }
i64 hamming(i64 a, i64 b, i64 l, i64 r) { return __builtin_popcountll(sub_bit(a, l, r) ^ sub_bit(b, l, r)); }
i64 compcount(i64 x) { return (__builtin_popcountll(x ^ (x >> 1)) + (x & 1)) / 2; }
i64 compcount2(i64 x) { return compcount(x & (x >> 1)); } // 長さ2以上の連結成分の個数
i64 adjacount(i64 x) { return __builtin_popcountll(x & (x >> 1)); } // 隣接する1のペアの個数
 
i64 next_combination(i64 x) {
    i64 t = x | (x - 1); return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctzll(x) + 1));
}
 
 
__int128_t POW(__int128_t x, int n) {
    __int128_t ret = 1;
    assert(n >= 0);
    if (x == 1 or n == 0) ret = 1;
    else if (x == -1 && n % 2 == 0) ret = 1; 
    else if (x == -1) ret = -1; 
    else if (n % 2 == 0) {
        assert(x < INFL);
        ret = POW(x * x, n / 2);
    } else {
        assert(x < INFL);
        ret = x * POW(x, n - 1);
    }
    return ret;
}
int per(int x, int y) { // x = qy + r (0 <= r < y) を満たすq
    assert(y != 0);
    if (x >= 0 && y > 0) return x / y;
    if (x >= 0 && y < 0) return x / y - (x % y < 0);
    if (x < 0 && y < 0) return x / y + (x % y < 0);
    return x / y - (x % y < 0); //  (x < 0 && y > 0) 
}
int mod(int x, int y) { // x = qy + r (0 <= r < y) を満たすr
    assert(y != 0);
    if (x >= 0) return x % y;
    __int128_t ret = x % y; // (x < 0)
    ret += (__int128_t)abs(y) * INFL;
    ret %= abs(y);
    return ret;
}
int floor(int x, int y) { // (ld)x / y 以下の最大の整数
    assert(y != 0);
    if (y < 0) x = -x, y = -y;
    return x >= 0 ? x / y : (x + 1) / y - 1;
}
int ceil(int x, int y) { // (ld)x / y 以上の最小の整数
    assert(y != 0);
    if (y < 0) x = -x, y = -y;
    return x > 0 ? (x - 1) / y + 1 : x / y;
}
int round(int x, int y) {
    assert(y != 0);
    return (x * 2 + y) / (y * 2);
}
int round(int x, int y, int k) { // (ld)(x/y)を10^kの位に関して四捨五入
    assert(y != 0); // TODO
    return INF;
}
int round2(int x, int y) { // 五捨五超入 // 未verify
    assert(y != 0);
    if (y < 0) y = -y, x = -x;
    int z = x / y;
    if ((z * 2 + 1) * y <= y * 2) z++;
    return z;
}
// int round(ld x, int k) { // xを10^kの位に関して四捨五入
// }
// int floor(ld x, int k) { // xを10^kの位に関してflooring
// }
// int ceil(ld x, int k) { // xを10^kの位に関してceiling
// }
// int kth(int x, int y, int k) { // x / yの10^kの位の桁
// }
int floor(ld x, ld y) { // 誤差対策TODO
    assert(!equals(y, 0));
    return floor(x / y);
    // floor(x) = ceil(x - 1) という話も
}
int ceil(ld x, ld y) { // 誤差対策TODO // ceil(p/q) = -floor(-(p/q))らしい
    assert(!equals(y, 0));
    return ceil(x / y);
    // ceil(x) = floor(x + 1)
}
int perl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす q
    // 未verify. 誤差対策TODO. EPS外してもいいかも。
    assert(!equals(y, 0));
    if (x >= 0 && y > 0) return floor(x / y)+EPS;
    if (x >= 0 && y < 0) return -floor(x / fabs(y));
    if (x < 0 && y < 0) return floor(x / y) + (x - floor(x/y)*y < -EPS);
    return floor(x / y) - (x - floor(x/y)*y < -EPS); //  (x < 0 && y > 0) 
}
ld modl(ld x, ld y) { // x = qy + r (0 <= r < y, qは整数) を満たす r
    // 未verify. 誤差対策TODO. -0.0が返りうる。
    assert(!equals(y, 0));
    if (x >= 0) return x - fabs(y)*fabs(per(x, y));
    return x - fabs(y)*floor(x, fabs(y));
}
int seisuu(ld x) { return (int)x; } // 整数部分. 誤差対策TODO
int modf(ld x) {
	if (x < 0) return ceill(x);
	else return floorl(x);
}
// 正なら+EPS, 負なら-EPSしてから、文字列に直して小数点以下を捨てる?
int seisuu(int x, int y) {
    assert(y != 0);
    return x / y;
}
int seisuu(ld x, ld y) { // 誤差対策TODO
    assert(!equals(y, 0));
    return (int)(x / y);
}
 
template <class T> pair<T, T> max(const pair<T, T> &a, const pair<T, T> &b) {
    if (a.first > b.first or a.first == b.first && a.second > b.second) return a;
    return b;
}
template <class T> pair<T, T> min(const pair<T, T> &a, const pair<T, T> &b) {
    if (a.first < b.first or a.first == b.first && a.second < b.second) return a;
    return b;
}
 
template <class T> bool chmax(T &a, const T& b) {
    if (a < b) { a = b; return true; } return false;
}
template <class T> bool chmin(T &a, const T& b) {
    if (a > b) { a = b; return true; } return false;
}
template <class T> T mid(T a, T b, T c) { // 誤差対策TODO
    return a + b + c - max({a, b, c}) - min({a, b, c});
}
template <class T> void Sort(T &a, T &b, bool rev = false) { 
    if (rev == false) {  // TODO テンプレート引数
        if (a > b) swap(a, b);
    } else {
        if (b > a) swap(b, a);
    }
}
template <class T> void Sort(T &a, T &b, T &c, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c); if (b > c) swap(b, c);
    } else {
        if (c > b) swap(c, b); if (c > a) swap(c, a); if (b > a) swap(b, a);
    }
}
template <class T> void Sort(T &a, T &b, T &c, T &d, bool rev = false) {
    if (rev == false) { 
        if (a > b) swap(a, b); if (a > c) swap(a, c);  if (a > d) swap(a, d);
        if (b > c) swap(b, c); if (b > d) swap(b, d); if (c > d) swap(c, d);
    } else {
        if (d > c) swap(d, c); if (d > b) swap(d, b); if (d > a) swap(d, a);
        if (c > b) swap(c, b); if (c > a) swap(c, a); if (b > a) swap(b, a);
    }
}
 
struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
 
    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};
 
class Compress {
public:
    int sz = 0;
    // gp_hash_table<int, int, custom_hash> Z, UZ;
    unordered_map<int, int> Z;    // 元の値 -> 圧縮した値
    unordered_map<int, int> UZ;   // 圧縮した値 -> 元の値
 
    Compress(const vector<int> &V, int base = 0) {
        this->sz = base;
        set<int> s(V.begin(), V.end());
 
        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
    
    Compress(const vector<int> &V1, const vector<int> &V2, int base = 0) {
        this->sz = base;
        vector<int> V3 = V2;
        V3.insert(V3.end(), V1.begin(), V1.end());
        set<int> s(V3.begin(), V3.end());
 
        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
 
    Compress(const vector<int> &V1, const vector<int> &V2, const vector<int> &V3, int base = 0) {
        this->sz = base;
        vector<int> V4 = V1;
        V4.insert(V4.end(), V2.begin(), V2.end());
        V4.insert(V4.end(), V3.begin(), V3.end());
        set<int> s(V4.begin(), V4.end());
 
        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
 
    Compress(const vector<int> &V1, const vector<int> &V2,
            const vector<int> &V3, const vector<int> &V4, int base = 0) {
        this->sz = base;
        vector<int> V5 = V1;
        V5.insert(V5.end(), V2.begin(), V2.end());
        V5.insert(V5.end(), V3.begin(), V3.end());
        V5.insert(V5.end(), V4.begin(), V4.end());
        set<int> s(V5.begin(), V5.end());
 
        for (int x : s) {
            this->Z[x] = this->sz;
            this->UZ[this->sz] = x;
            this->sz++;
        }
    }
 
    vector<int> zip(const vector<int> &V) {
        vector<int> ret = V;
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = Z[ret[i]];
        }
        return ret;
    }
 
    vector<int> unzip(const vector<int> &V) {
        vector<int> ret = V;
        for (int i = 0; i < (int)V.size(); i++) {
            ret[i] = UZ[ret[i]];
        }
        return ret;
    }
 
    int size() { return sz; }
 
    int encode(int x) { return Z[x]; }
    int decode(int x) {
        if (UZ.find(x) == UZ.end()) return -1; // xが元の配列に存在しないとき
        return UZ[x];
    }
};
 
class UnionFind {
public:
	UnionFind() = default;
    UnionFind(int N) : par(N), sz(N, 1) {
        iota(par.begin(), par.end(), 0);
    }
	int root(int x) {
		if (par[x] == x) return x;
		return (par[x] = root(par[x]));
	}
	bool unite(int x, int y) {
		int rx = root(x);
		int ry = root(y);
        if (rx == ry) return false;
		if (sz[rx] < sz[ry]) swap(rx, ry);
		sz[rx] += sz[ry];
		par[ry] = rx;
        return true;
	}
	bool issame(int x, int y) { return (root(x) == root(y)); }
	int size(int x) { return sz[root(x)]; }
    vector<vector<int>> groups(int N) {
        vector<vector<int>> G(N);
        for (int x = 0; x < N; x++) {
            G[root(x)].push_back(x);
        }
		G.erase( remove_if(G.begin(), G.end(),
            [&](const vector<int>& V) { return V.empty(); }), G.end());
        return G;
    }
private:
	vector<int> par, sz;
};
 
template<typename T>
struct BIT {
    int N;             // 要素数
    vector<T> bit[2];  // データの格納先
    BIT(int N_, int x = 0) {
        N = N_ + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        if (x != 0) {
            for (int i = 0; i < N; i++) add(i, x);
        }
    }
    BIT(const vector<T> &A) {
        N = A.size() + 1;
        bit[0].assign(N, 0); bit[1].assign(N, 0);
        for (int i = 0; i < (int)A.size(); i++) add(i, A[i]);
    }
    void add_sub(int p, int i, T x) {
        while (i < N) { bit[p][i] += x; i += (i & -i); }
    }
    void add(int l, int r, T x) {
        add_sub(0, l + 1, -x * l); add_sub(0, r + 1, x * r);
        add_sub(1, l + 1, x); add_sub(1, r + 1, -x);
    }
    void add(int i, T x) { add(i, i + 1, x); }
    T sum_sub(int p, int i) {
        T ret = 0;
        while (i > 0) { ret += bit[p][i]; i -= (i & -i); }
        return ret;
    }
    T sum(int i) { return sum_sub(0, i) + sum_sub(1, i) * i; }
    T sum(int l, int r) { return sum(r) - sum(l); }
    T get(int i) { return sum(i, i + 1); }
    void set(int i, T x) { T s = get(i); add(i, -s + x); }
};
 
template<int mod> class Modint {
public:
    int val = 0;
    Modint(int x = 0) { while (x < 0) x += mod; val = x % mod; }
    Modint(const Modint &r) { val = r.val; }
 
    Modint operator -() { return Modint(-val); } // 単項
    Modint operator +(const Modint &r) { return Modint(*this) += r; }
    Modint operator +(const int &q) { Modint r(q); return Modint(*this) += r; }
    Modint operator -(const Modint &r) { return Modint(*this) -= r; }
    Modint operator -(const int &q) { Modint r(q); return Modint(*this) -= r; }
    Modint operator *(const Modint &r) { return Modint(*this) *= r; }
    Modint operator *(const int &q) { Modint r(q); return Modint(*this) *= r; }
    Modint operator /(const Modint &r) { return Modint(*this) /= r; }
    Modint operator /(const int &q) { Modint r(q); return Modint(*this) /= r; }
    
    Modint& operator ++() { val++; if (val >= mod) val -= mod; return *this; } // 前置
    Modint operator ++(signed) { ++*this; return *this; } // 後置
    Modint& operator --() { val--; if (val < 0) val += mod; return *this; }
    Modint operator --(signed) { --*this; return *this; }
    Modint &operator +=(const Modint &r) { val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator +=(const int &q) { Modint r(q); val += r.val; if (val >= mod) val -= mod; return *this; }
    Modint &operator -=(const Modint &r) { if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator -=(const int &q) { Modint r(q);  if (val < r.val) val += mod; val -= r.val; return *this; }
    Modint &operator *=(const Modint &r) { val = val * r.val % mod; return *this; }
    Modint &operator *=(const int &q) { Modint r(q); val = val * r.val % mod; return *this; }
    Modint &operator /=(const Modint &r) {
        int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    Modint &operator /=(const int &q) {
        Modint r(q); int a = r.val, b = mod, u = 1, v = 0;
        while (b) {int t = a / b; a -= t * b; swap(a, b); u -= t * v; swap(u, v);}
        val = val * u % mod; if (val < 0) val += mod;
        return *this;
    }
    bool operator ==(const Modint& r) { return this -> val == r.val; }
    bool operator <(const Modint& r) { return this -> val < r.val; }
    bool operator >(const Modint& r) { return this -> val > r.val; }
    bool operator !=(const Modint& r) { return this -> val != r.val; }
};
 
using mint = Modint<MOD>;
 
istream &operator >>(istream &is, mint& x) {
    int t; is >> t; x = t; return (is);
}
ostream &operator <<(ostream &os, const mint& x) {
    return os << x.val;
}
mint modpow(const mint &x, int n) {
    if (n < 0) return (mint)1 / modpow(x, -n); // 未verify
    assert(n >= 0);
    if (n == 0) return 1;
    mint t = modpow(x, n / 2);
    t = t * t;
    if (n & 1) t = t * x;
    return t;
}
 
int modpow(__int128_t x, int n, int mod) {
    assert(n >= 0 && mod > 0); // TODO: n <= -1
    __int128_t ret = 1;
    while (n > 0) {
        if (n % 2 == 1) ret = ret * x % mod;
        x = x * x % mod;
        n /= 2;
    }
    return ret;
}
int modinv(__int128_t x, int mod) {
    assert(mod > 0);
    // assert(x > 0);
    if (x == 1 or x == 0) return 1;
    return mod - modinv(mod % x, mod) * (mod / x) % mod;
}
 
istream &operator >>(istream &is, __int128_t& x) {
    string S; is >> S;
    __int128_t ret = 0;
    int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9')
            ret = ret * 10 + S[i] - '0';
    x = ret * f;
    return (is);
}
ostream &operator <<(ostream &os, __int128_t x) {
    ostream::sentry s(os);
    if (s) {
        __uint128_t tmp = x < 0 ? -x : x;
        char buffer[128]; char *d = end(buffer);
        do {
            --d; *d = "0123456789"[tmp % 10]; tmp /= 10;
        } while (tmp != 0);
        if (x < 0) { --d; *d = '-'; }
        int len = end(buffer) - d;
        if (os.rdbuf()->sputn(d, len) != len) os.setstate(ios_base::badbit);
    }
    return os;
}
 
__int128_t stoll(string &S) {
    __int128_t ret = 0; int f = 1;
    if (S[0] == '-') f = -1; 
    for (int i = 0; i < S.length(); i++)
        if ('0' <= S[i] && S[i] <= '9') ret = ret * 10 + S[i] - '0';
    return ret * f;
}
__int128_t gcd(__int128_t a, __int128_t b) { return b ? gcd(b, a % b) : a; }
__int128_t lcm(__int128_t a, __int128_t b) {
    return a / gcd(a, b) * b;
    // lcmが__int128_tに収まる必要あり
}
 
string to_string(ld x, int k) { // xの小数第k位までをstring化する
    assert(k >= 0);
    stringstream ss;
    ss << setprecision(k + 2) << x;
    string s = ss.str();
    if (s.find('.') == string::npos) s += '.';
    int pos = s.find('.');
    for (int i = 0; k >= (int)s.size() - 1 - pos; i++) s += '0';
    s.pop_back();
    if (s.back() == '.') s.pop_back();
    return s;
 
    // stringstream ss; // 第k+1位を四捨五入して第k位まで返す
    // ss << setprecision(k + 1) << x;
    // string s = ss.str();
    // if (s.find('.') == string::npos) s += '.';
    // int pos = s.find('.');
    // for (int i = 0; k > (int)s.size() - 1 - pos; i++) s += '0';
    // if (s.back() == '.') s.pop_back();
    // return s;
}
string to_string(__int128_t x) {
    string ret = "";
    if (x < 0) { ret += "-"; x *= -1; }
    while (x) { ret += (char)('0' + x % 10); x /= 10; }
    reverse(ret.begin(), ret.end());
    return ret;
}
string to_string(char c) { string s = ""; s += c; return s; }
 
template<class T> size_t HashCombine(const size_t seed,const T &v) {
    return seed^(hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2));
}
template<class T,class S> struct hash<pair<T,S>>{
    size_t operator()(const pair<T,S> &keyval) const noexcept {
        return HashCombine(hash<T>()(keyval.first), keyval.second);
    }
};
template<class T> struct hash<vector<T>>{
    size_t operator()(const vector<T> &keyval) const noexcept {
        size_t s=0;
        for (auto&& v: keyval) s=HashCombine(s,v);
        return s;
    }
};
template<int N> struct HashTupleCore{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{
        size_t s=HashTupleCore<N-1>()(keyval);
        return HashCombine(s,get<N-1>(keyval));
    }
};
template <> struct HashTupleCore<0>{
    template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; }
};
template<class... Args> struct hash<tuple<Args...>>{
    size_t operator()(const tuple<Args...> &keyval) const noexcept {
        return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval);
    }
};
 
vector<mint> _fac, _finv, _inv;
void COMinit(int N) {
    _fac.resize(N + 1); _finv.resize(N + 1);  _inv.resize(N + 1);
    _fac[0] = _fac[1] = 1; _finv[0] = _finv[1] = 1; _inv[1] = 1;
    for (int i = 2; i <= N; i++) {
        _fac[i] = _fac[i-1] * mint(i);
        _inv[i] = -_inv[MOD % i] * mint(MOD / i);
        _finv[i] = _finv[i - 1] * _inv[i];
    }
}
 
mint FAC(int N) {
    if (N < 0) return 0; return _fac[N];
}
mint COM(int N, int K) {
    if (N < K) return 0; if (N < 0 or K < 0) return 0;
    return _fac[N] * _finv[K] * _finv[N - K];
}
mint PERM(int N, int K) {
    if (N < K) return 0; if (N < 0 or K < 0) return 0;
    return _fac[N] *  _finv[N - K];
}
mint NHK(int N, int K) { // initのサイズに注意
    if (N == 0 && K == 0)  return 1;
    return COM(N + K - 1, K);
}
 
#pragma endregion

// https://hashiryo.github.io/Library/src/DataStructure/SortedPerBucket.hpp
template <class T, int B= 700> class SortedPerBucket {
 static constexpr T INF= numeric_limits<T>::max() / 2;
 struct Dat {
  const int n;
  T a[B], sorted[B], acc[B + 1];
  T add, lb, ub;
  Dat(int b): n(b), a{0}, sorted{0}, acc{0}, add(0), lb(-INF), ub(INF) {}
  Dat(const T *bg, int b): n(b), a{0}, acc{0}, add(0), lb(-INF), ub(INF) {
   for (int i= n; i--;) a[i]= *(bg + i);
   build();
  }
  inline bool eval() {
   if (add == 0 && lb == -INF && ub == INF) return false;
   for (auto &x: a) x= clamp(x, lb, ub) + add;
   return add= 0, lb= -INF, ub= INF, true;
  }
  inline void build() { copy_n(a, B, sorted), sort(sorted, sorted + n), partial_sum(sorted, sorted + n, acc + 1); }
  inline int idx(T x) const { return lower_bound(sorted, sorted + n, x) - sorted; }
  inline int count(T x) const { return x-= add, (x <= lb ? 0 : ub < x ? n : idx(x)); }
  inline T sum() const {
   int l= idx(lb), u= idx(ub);
   return acc[u] - acc[l] + lb * l + ub * (n - u) + add * n;
  }
  inline T sum(T x) const {
   if (x-= add; x <= lb) return 0;
   if (ub < x) return sum();
   int l= idx(lb), u= idx(x);
   return acc[u] - acc[l] + lb * l + add * u;
  }
  inline T get(int k) const { return clamp(a[k], lb, ub) + add; }
 };
 const int n;
 vector<Dat> dat;
 template <class U, class All, class One> inline U fold(int l, int r, const All &all, const One &one) const {
  U ret= 0;
  if (int i= l / B, j= r / B, k= l % B, m= r % B; i < j) {
   if (k) {
    for (; k < dat[i].n; ++k) ret+= one(dat[i].get(k));
    ++i;
   }
   for (; i < j; ++i) ret+= all(dat[i]);
   for (; m--;) ret+= one(dat[j].get(m));
  } else
   for (; k < m; ++k) ret+= one(dat[i].get(k));
  return ret;
 }
 template <class All, class One> inline void update(int l, int r, const All &all, const One &one) {
  if (int i= l / B, j= r / B, k= l % B, m= r % B; i < j) {
   if (k) {
    for (dat[i].eval(); k < dat[i].n; k++) one(dat[i].a[k]);
    dat[i].build(), ++i;
   }
   for (; i < j; ++i) all(dat[i]);
   if (m) {
    for (dat[j].eval(); m--;) one(dat[j].a[m]);
    dat[j].build();
   }
  } else {
   for (dat[i].eval(); k < m; ++k) one(dat[i].a[k]);
   dat[i].build();
  }
 }
public:
    SortedPerBucket(int n): n(n) {
        for (int l= 0, r; l < n; l= r) r= min(l + B, n), dat.emplace_back(r - l);
    }
    SortedPerBucket(const vector<T> &a): n(a.size()) {
        for (int l= 0, r; l < n; l= r) r= min(l + B, n), dat.emplace_back(a.data() + l, r - l);
    }
    // count i s.t. (l <= i < r) && (a[i] < ub)
    int count(int l, int r, T ub) const {
        return fold<int>(
            l, r, [&](const Dat &d) { return d.count(ub); }, [&](T x) { return x < ub; });
    }
    // count i s.t. (l <= i < r) && (lb <= a[i] < ub)
    int count(int l, int r, T lb, T ub) const { return count(l, r, ub) - count(l, r, lb); }
    // sum a[i] s.t. (l <= i < r)
    T sum(int l, int r) const {
        return fold<T>(
            l, r, [&](const Dat &d) { return d.sum(); }, [&](T x) { return x; });
    }
    // sum a[i] s.t. (l <= i < r) && (a[i] < ub)
    T sum(int l, int r, T ub) const {
        return fold<T>(
            l, r, [&](const Dat &d) { return d.sum(ub); }, [&](T x) { return x < ub ? x : 0; });
    }
        // sum a[i] s.t. (l <= i < r)  && (lb <= a[i] < ub)
    T sum(int l, int r, T lb, T ub) const { return sum(l, r, ub) - sum(l, r, lb); }
    void set(int k, T x) {
        int i= k / B, j= k % B;
        dat[i].eval(), dat[i].a[j]= x, dat[i].build();
    }
    T get(int k) const { return dat[k / B].get(k % B); }
    T operator[](int k) const { return get(k); }
    void add(int l, int r, T v) {
        update(
            l, r, [&](Dat &d) { d.add+= v; }, [&](T &x) { x+= v; });
    }
    void chmin(int l, int r, T ub) {
        auto f= [&](Dat &d) {
            T b= ub - d.add;
            d.ub= min(d.ub, b), d.lb= min(d.lb, b);
        };
        update(l, r, f, [&](T &x) { x= min(x, ub); });
    }
    void chmax(int l, int r, T lb) {
        auto f= [&](Dat &d) {
            T a= lb - d.add;
            d.lb= max(d.lb, a), d.ub= max(d.ub, a);
        };
        update(l, r, f, [&](T &x) { x= max(x, lb); });
    }
    void chclamp(int l, int r, T lb, T ub) {
        auto f= [&](Dat &d) {
            T a= lb - d.add, b= ub - d.add;
            d.ub= clamp(d.ub, a, b), d.lb= clamp(d.lb, a, b);
        };
        update(l, r, f, [&](T &x) { x= clamp(x, lb, ub); });
    }
};

signed main() {
    int N, Q;
    cin >> N >> Q;
    vector<int> A(N);
    for (int i = 0; i < N; i++) cin >> A[i];

    SortedPerBucket<long long, 100> seg(A);
    for (int i = 0; i < Q; i++) {
        int t;
        cin >> t;
        if (t == 1) {
            int l, r, x;
            cin >> l >> r >> x;
            l--; r--; 
            seg.chmin(l, r + 1, x);
        }
        if (t == 2) {
            int l, r, x;
            cin >> l >> r >> x;
            l--; r--; 
            seg.chmax(l, r + 1, x);
        }
        if (t == 3) {
            int l, r, x;
            cin >> l >> r >> x;
            l--; r--; 
            seg.add(l, r + 1, x);
        }
        if (t == 4) {
            int l, r, a, b;
            cin >> l >> r >> a >> b;
            l--; r--; 
            cout << seg.count(l, r + 1, a, b + 1) << endl;
        }
    }
}
accuracy: 1
time_ms: 1060
memory_kb: 7632
final_rank: 13

code_snippet: #line 1 "library-cpp/other/template.hpp"
// clang-format off
#include <bits/stdc++.h>
using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
using i128 = __int128_t;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
template <class T> using maxheap = priority_queue<T>;
template <class T> using minheap = priority_queue<T, vector<T>, greater<T>>;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vector<T>>;
#define OVERLOAD_REP(_1, _2, _3, name, ...) name
#define REP0(n) for (auto minato = decay_t<decltype(n)>{}; minato < (n); ++minato)
#define REP1(i, n) for (auto i = decay_t<decltype(n)>{}; (i) < (n); (i)++)
#define REP2(i, l, r) for (auto i = (l); (i) < (r); (i)++)
#define rep(...) OVERLOAD_REP(__VA_ARGS__, REP2, REP1, REP0)(__VA_ARGS__)
#define OVERLOAD_RREP(_1, _2, _3, name, ...) name
#define RREP1(i, n) for (auto i = (n) - 1; (i) >= decay_t<decltype(n)>{}; (i)--)
#define RREP2(i, l, r) for (auto i = (r) - 1; (i) >= (l); (i)--)
#define rrep(...) OVERLOAD_RREP(__VA_ARGS__, RREP2, RREP1)(__VA_ARGS__)
#define all(x) begin(x), end(x)
template <class Container> int SZ(const Container& v) { return int(v.size()); }
template <class T> void UNIQUE(vector<T>& v) { v.erase(unique(v.begin(), v.end()), v.end()); }
template <class T> T MAX(const vector<T>& v) { return *max_element(v.begin(), v.end()); }
template <class T> T MIN(const vector<T>& v) { return *min_element(v.begin(), v.end()); }
template <class T> T SUM(const vector<T>& v) { return accumulate(v.begin(), v.end(), T(0)); }
template <class T> T ABS(T x) { return max(x, -x); }
template <class T1, class T2> bool chmax(T1& a, T2 b) { if (a < b) { a = b; return true; } return false; }
template <class T1, class T2> bool chmin(T1& a, T2 b) { if (a > b) { a = b; return true; } return false; }
int topbit(ull x) { return x == 0 ? -1 : 63 - __builtin_clzll(x); }
int botbit(ull x) { return x == 0 ? 64 : __builtin_ctzll(x); }
int popcount(ull x) { return __builtin_popcountll(x); }
int kthbit(ull x, int k) { return (x >> k) & 1; }
constexpr long long TEN(int x) { return x == 0 ? 1 : TEN(x - 1) * 10; }
template <typename S> void rearrange(const vector<S>& id) { (void)id; }
template <typename S, typename T> void rearrange_exec(const vector<S>& id, vector<T>& v) { vector<T> w(v.size()); for (size_t i = 0; i < id.size(); i++) { w[i] = v[id[i]]; } v.swap(w); }
template <typename S, typename Head, typename... Tail> void rearrange(const vector<S>& id, Head& a, Tail& ...tail) { rearrange_exec(id, a); rearrange(id, tail...); }
istream& operator>>(istream& is, __int128_t& x) {
    x = 0;
    string s;
    is >> s;
    int n = int(s.size()), it = 0;
    if (s[0] == '-') it++;
    for (; it < n; it++) x = (x * 10 + s[it] - '0');
    if (s[0] == '-') x = -x;
    return is;
}
ostream& operator<<(ostream& os, __int128_t x) {
    if (x == 0) return os << 0;
    if (x < 0) os << '-', x = -x;
    deque<int> deq;
    while (x) deq.emplace_front(x % 10), x /= 10;
    for (int e : deq) os << e;
    return os;
}
template <class T> vector<T> &operator++(vector<T>& v) { for (auto& e : v) { e++; } return v;} 
template <class T> vector<T> operator++(vector<T>& v, int) { auto res = v; for (auto& e : v) { e++; } return res; }
template <class T> vector<T> &operator--(vector<T>& v) { for (auto& e : v) { e--; } return v; }
template <class T> vector<T> operator--(vector<T>& v, int) { auto res = v; for (auto& e : v) { e--; } return res; }
template <class T1, class T2> pair<T1, T2> operator-(const pair<T1, T2>& x) { return pair<T1, T2>(-x.first, -x.second); }
template <class T1, class T2> pair<T1, T2> operator-(const pair<T1, T2>& x, const pair<T1, T2>& y) { return pair<T1, T2>(x.first - y.first, x.second - y.second); }
template <class T1, class T2> pair<T1, T2> operator+(const pair<T1, T2>& x, const pair<T1, T2>& y) { return pair<T1, T2>(x.first + y.first, x.second + y.second); }
template <class T1, class T2> pair<T1, T2> operator+=(pair<T1, T2>& l, const pair<T1, T2>& r) { return l = l + r; }
template <class T1, class T2> pair<T1, T2> operator-=(pair<T1, T2>& l, const pair<T1, T2>& r) { return l = l - r; }
constexpr char ln = '\n';
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
void YES(bool t = true) { cout << YESNO[t] << "\n"; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = true) { cout << YesNo[t] << "\n"; }
void No(bool t = 1) { Yes(!t); }
template <class T> void drop(T x) { cout << x << "\n"; exit(0); }
#define INT(...)     \
    int __VA_ARGS__; \
    IN(__VA_ARGS__)
#define LL(...)     \
    ll __VA_ARGS__; \
    IN(__VA_ARGS__)
#define STR(...)        \
    string __VA_ARGS__; \
    IN(__VA_ARGS__)
#define CHR(...)      \
    char __VA_ARGS__; \
    IN(__VA_ARGS__)
#define LDB(...)             \
    long double __VA_ARGS__; \
    IN(__VA_ARGS__)
#define VEC(type, name, size) \
    vector<type> name(size);  \
    IN(name)
#define VEC2(type, name1, name2, size)     \
    vector<type> name1(size), name2(size); \
    for (int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)           \
    vector<type> name1(size), name2(size), name3(size); \
    for (int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define VEC4(type, name1, name2, name3, name4, size)                 \
    vector<type> name1(size), name2(size), name3(size), name4(size); \
    for (int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i], name4[i]);
#define VV(type, name, N, M)                       \
    vector<vector<type>> name(N, vector<type>(M)); \
    IN(name)
template <class T> void scan(T& a) { cin >> a; }
template <class T> void scan(vector<T>& a) { for (auto& i : a) scan(i); }
void IN() {}
template <class Head, class... Tail> void IN(Head& head, Tail&... tail) { scan(head); IN(tail...); }
void print() { cout << "\n"; }
template <class T> void print(const vector<T>& v) { for (auto it = v.begin(); it != v.end(); ++it) { if (it != v.begin()) { cout << " "; } cout << *it; } print(); }
template <class T, class... Args> void print(const T& x, const Args& ... args) { cout << x; if (sizeof...(Args)) cout << " "; print(args...); }
#ifdef MINATO_LOCAL
template <class T1, class T2> ostream& operator<<(ostream& os, pair<T1, T2> p) { return os << "(" << p.first << ", " << p.second << ")"; }
template <size_t N, class TUPLE> void debug_tuple(ostream& os, TUPLE _) { (void)os; (void)_; }
template <size_t N, class TUPLE, class T, class ...Args> void debug_tuple(ostream &os, TUPLE t) { os << (N == 0 ? "" : ", ") << get<N>(t); debug_tuple<N + 1, TUPLE, Args...>(os, t); }
template <class ...Args> ostream& operator<<(ostream& os, tuple<Args...> t) { os << "("; debug_tuple<0, tuple<Args...>, Args...>(os, t); return os << ")"; }
string debug_delim(int& i) { return i++ == 0 ? "" : ", "; }
#define debug_embrace(x) { int i = 0; os << "{";  { x } return os << "}"; }
template <class T> ostream& operator<<(ostream& os, vector<T> v) { debug_embrace( for (T e : v) { os << debug_delim(i) << e; } ) }
template <class T, size_t N> ostream& operator<<(ostream& os, array<T, N> a) { debug_embrace( for (T e : a) { os << debug_delim(i) << e; } ) }
template <class T, size_t N> enable_if_t<!is_same_v<char, remove_cv_t<T>>, ostream>& operator<<(ostream& os, T(&a)[N]) { debug_embrace( for (T e : a) { os << debug_delim(i) << e; } ) }
template <class Key> ostream& operator<<(ostream& os, set<Key> s) { debug_embrace( for (Key e : s) { os << debug_delim(i) << e; }) }
template <class Key, class T> ostream& operator<<(ostream& os, map<Key, T> mp) { debug_embrace( for (auto e : mp) { os << debug_delim(i) << e; }) }
template <class Key> ostream& operator<<(ostream& os, multiset<Key> s) { debug_embrace( for (Key e : s) { os << debug_delim(i) << e; }) }
template <class T> ostream& operator<<(ostream& os, queue<T> q) { debug_embrace( for (; !q.empty(); q.pop()) { os << debug_delim(i) << q.front(); } ) }
template <class T> ostream& operator<<(ostream& os, deque<T> q) { debug_embrace( for (T e : q) { os << debug_delim(i) << e; } ) }
template <class T> ostream& operator<<(ostream& os, priority_queue<T> q) { debug_embrace( for (; !q.empty(); q.pop()) { os << debug_delim(i) << q.top(); } ) }
template <class T> ostream& operator<<(ostream& os, priority_queue<T, vector<T>, greater<T>> q) { debug_embrace( for (; !q.empty(); q.pop()) { os << debug_delim(i) << q.top(); } ) }
void debug_out() { cerr << endl; }
template <class T, class... Args> void debug_out(const T& x, const Args& ... args) { cerr << " " << x; debug_out(args...); }
#define debug(...) cerr << __LINE__ << " : [" << #__VA_ARGS__ << "] =", debug_out(__VA_ARGS__)
#else
#define debug(...) (void(0))
#endif
struct fast_ios { fast_ios() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(20); cerr << fixed << setprecision(7); }; } fast_ios_;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// clang-format on
#line 2 "E.cpp"

template <int W> struct SquareRootDecomposition {
    struct Ranges {
        optional<pair<int, int>> left_overflow_range;
        optional<pair<int, int>> bucket_range;
        optional<pair<int, int>> right_overflow_range;
        Ranges()
            : left_overflow_range(nullopt),
              bucket_range(nullopt),
              right_overflow_range(nullopt) {
        }
    };

    int n;

    SquareRootDecomposition() {
    }
    SquareRootDecomposition(int n) : n(n) {
    }

    int bucket_size() const {
        return (n + W - 1) / W;
    }

    /**
     * @brief クエリの範囲を分割する
     * @param l 左端
     * @param r 右端
     * @return 分割された範囲
     * @note [l, r) の範囲を分割する
     */
    Ranges query(int l, int r) const {
        assert(0 <= l && l < r && r <= n);
        Ranges ret;
        int l_bucket_id = bucket_id(l);
        int r_bucket_id = bucket_id(r - 1);
        auto [l_bucket_l, l_bucket_r] = bucket_range(l_bucket_id);
        auto [r_bucket_l, r_bucket_r] = bucket_range(r_bucket_id);
        if (l_bucket_id == r_bucket_id) {
            if (l == l_bucket_l && r == r_bucket_r) {
                ret.bucket_range = {l_bucket_id, l_bucket_id + 1};
            } else {
                ret.left_overflow_range = {l, r};
            }
        } else {
            if (l_bucket_id + 1 < r_bucket_id) {
                ret.bucket_range = {l_bucket_id + 1, r_bucket_id};
            }
            if (l == l_bucket_l) {
                if (ret.bucket_range) {
                    ret.bucket_range->first--;
                } else {
                    ret.bucket_range = {l_bucket_id, l_bucket_id + 1};
                }
            } else {
                ret.left_overflow_range = {l, l_bucket_r};
            }
            if (r == r_bucket_r) {
                if (ret.bucket_range) {
                    ret.bucket_range->second++;
                } else {
                    ret.bucket_range = {r_bucket_id, r_bucket_id + 1};
                }
            } else {
                ret.right_overflow_range = {r_bucket_l, r};
            }
        }
        return ret;
    }

    int bucket_id(int i) const {
        assert(0 <= i && i < n);
        return i / W;
    }

    pair<int, int> bucket_range(int i) const {
        assert(0 <= i && i < bucket_size());
        int l = i * W;
        int r = min((i + 1) * W, n);
        return {l, r};
    }
};

void solve() {
    constexpr ll INF = TEN(18);
    INT(N, Q);
    VEC(ll, A, N);

    SquareRootDecomposition<128> decomp(N);
    auto B = A;
    vec<ll> add(decomp.bucket_size(), 0);
    vec<ll> mn(decomp.bucket_size(), -INF);
    vec<ll> mx(decomp.bucket_size(), INF);
    // 足したあと切り詰める
    auto upd = [&](int k) {
        auto [l, r] = decomp.bucket_range(k);
        rep(i, l, r) A[i] += add[k];
        add[k] = 0;
        rep(i, l, r) A[i] = clamp(A[i], mn[k], mx[k]);
        rep(i, l, r) B[i] = A[i];
        sort(B.begin() + l, B.begin() + r);
        mn[k] = -INF;
        mx[k] = INF;
    };
    auto lazy = [&](int k, int t, ll x) {
        if (t == 1) {
            chmin(mn[k], x);
            chmin(mx[k], x);
        } else if (t == 2) {
            chmax(mn[k], x);
            chmax(mx[k], x);
        } else {
            add[k] += x;
            mn[k] += x;
            mx[k] += x;
        }
    };
    rep(i, decomp.bucket_size()) upd(i);
    rep(Q) {
        INT(t);
        if (t == 1) {
            LL(l, r, x);
            l--;
            auto ranges = decomp.query(l, r);
            if (ranges.left_overflow_range) {
                auto [p, q] = ranges.left_overflow_range.value();
                upd(decomp.bucket_id(p));
                rep(j, p, q) chmin(A[j], x);
                upd(decomp.bucket_id(p));
            }
            if (ranges.bucket_range) {
                auto [p, q] = ranges.bucket_range.value();
                rep(j, p, q) {
                    lazy(j, t, x);
                }
            }
            if (ranges.right_overflow_range) {
                auto [p, q] = ranges.right_overflow_range.value();
                debug(p, q);
                upd(decomp.bucket_id(p));
                rep(j, p, q) chmin(A[j], x);
                upd(decomp.bucket_id(p));
            }
        } else if (t == 2) {
            LL(l, r, x);
            l--;
            auto ranges = decomp.query(l, r);
            if (ranges.left_overflow_range) {
                auto [p, q] = ranges.left_overflow_range.value();
                upd(decomp.bucket_id(p));
                rep(j, p, q) chmax(A[j], x);
                upd(decomp.bucket_id(p));
            }
            if (ranges.bucket_range) {
                auto [p, q] = ranges.bucket_range.value();
                rep(j, p, q) {
                    lazy(j, t, x);
                }
            }
            if (ranges.right_overflow_range) {
                auto [p, q] = ranges.right_overflow_range.value();
                upd(decomp.bucket_id(p));
                rep(j, p, q) chmax(A[j], x);
                upd(decomp.bucket_id(p));
            }

        } else if (t == 3) {
            LL(l, r, x);
            l--;
            auto ranges = decomp.query(l, r);
            if (ranges.left_overflow_range) {
                auto [p, q] = ranges.left_overflow_range.value();
                upd(decomp.bucket_id(p));
                rep(j, p, q) A[j] += x;
                upd(decomp.bucket_id(p));
            }
            if (ranges.bucket_range) {
                auto [p, q] = ranges.bucket_range.value();
                rep(j, p, q) {
                    lazy(j, t, x);
                }
            }
            if (ranges.right_overflow_range) {
                auto [p, q] = ranges.right_overflow_range.value();
                upd(decomp.bucket_id(p));
                rep(j, p, q) A[j] += x;
                upd(decomp.bucket_id(p));
            }

        } else {
            LL(l, r, x, y);
            l--;
            auto ranges = decomp.query(l, r);
            int ans = 0;
            if (ranges.left_overflow_range) {
                auto [p, q] = ranges.left_overflow_range.value();
                upd(decomp.bucket_id(p));
                rep(j, p, q) {
                    if (x <= A[j] && A[j] <= y) ans++;
                }
            }
            if (ranges.bucket_range) {
                auto [p, q] = ranges.bucket_range.value();
                rep(j, p, q) {
                    if (mn[j] > y || mx[j] < x) continue;
                    auto [a, b] = decomp.bucket_range(j);
                    int lb =
                        lower_bound(B.begin() + a, B.begin() + b, x - add[j]) -
                        B.begin();
                    int ub =
                        upper_bound(B.begin() + a, B.begin() + b, y - add[j]) -
                        B.begin();
                    if (mn[j] >= x) lb = a;
                    if (mx[j] <= y) ub = b;
                    ans += ub - lb;
                }
            }
            if (ranges.right_overflow_range) {
                auto [p, q] = ranges.right_overflow_range.value();
                upd(decomp.bucket_id(p));
                rep(j, p, q) {
                    if (x <= A[j] && A[j] <= y) ans++;
                }
            }
            print(ans);
        }
    }
}

int main() {
    int T = 1;
    // cin >> T;
    for (int i = 0; i < T; i++) {
        solve();
    }
}
accuracy: 1
time_ms: 1320
memory_kb: 4684
final_rank: 10

code_snippet: // #pragma GCC optimize ("O3")
// #pragma GCC target("avx512f")
// #pragma GCC optimize("unroll-loops")
// #ifndef ONLINE_JUDGE
// #define _GLIBCXX_DEBUG
// #endif
#include<bits/stdc++.h>
// #include <boost/multiprecision/cpp_dec_float.hpp>
// #include <boost/multiprecision/cpp_int.hpp>
// #include <boost/rational.hpp>
// namespace mp = boost::multiprecision;
// using Bint=mp::cpp_int;
// using Real = mp::number<mp::cpp_dec_float<64>>;
// #include<atcoder/all>
using namespace std;
// using namespace atcoder;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rep1(n) for(ll i = 0; i < (n); ++i)
#define rep2(i, n) for(ll i = 0; i < (n); ++i)
#define rep3(i, a, b) for(ll i = (a); i < (b); ++i)
#define rep4(i, a, b, c) for(ll i = (a); i < (b); i += (c))
#define rrep(i, a, b) for(ll i = (b); i --> (a); )
int scan(){ return getchar(); }
void scan(int& a){ scanf("%d", &a); }
void scan(unsigned& a){ scanf("%u", &a); }
void scan(long long& a){ scanf("%lld", &a); }
void scan(unsigned long long& a){ scanf("%llu", &a); }
void scan(char& a){ do{ a = getchar(); }while(a == ' ' || a == '\n'); }
void scan(float& a){ scanf("%f", &a); }
void scan(double& a){ scanf("%lf", &a); }
void scan(long double& a){ scanf("%Lf", &a); }
void scan(vector<bool>& a){ for(unsigned i = 0; i < a.size(); i++) { int b; scan(b); a[i] = b; } }
void scan(char a[]){ scanf("%s", a); }
void scan(string& a){ cin >> a; }
template<class T> void scan(vector<T>&);
template<class T> void scan(deque<T>&);
template<class T, size_t size> void scan(array<T, size>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T, size_t size> void scan(T(&)[size]);
template<class T> void scan(vector<T>& a){ for(auto& i : a) scan(i); }
template<class T> void scan(deque<T>& a){ for(auto& i : a) scan(i); }
template<class T, size_t size> void scan(array<T, size>& a){ for(auto& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto& i : a) scan(i); }
template<class T> void scan(T& a){ cin >> a; }
void in(){}
template <class Head, class... Tail> void in(Head& head, Tail&... tail){ scan(head); in(tail...); }
void print(){ putchar(' '); }
void print(bool a){ printf("%d", a); }
void print(int a){ printf("%d", a); }
void print(unsigned a){ printf("%u", a); }
void print(long long a){ printf("%lld", a); }
void print(unsigned long long a){ printf("%llu", a); }
void print(char a){ printf("%c", a); }
void print(char a[]){ printf("%s", a); }
void print(float a){ printf("%.15f", a); }
void print(double a){ printf("%.15f", a); }
void print(long double a){ printf("%.15Lf", a); }
void print(const string& a){ for(auto&& i : a) print(i); }
template<class T> void print(const vector<T>&);
template<class T, size_t size> void print(const array<T, size>&);
template<class T, class L> void print(const pair<T, L>& p);
template<class T, size_t size> void print(const T (&)[size]);
template<class T> void print(const vector<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T> void print(const deque<T>& a){ if(a.empty()) return; print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, size_t size> void print(const array<T, size>& a){ print(a[0]); for(auto i = a.begin(); ++i != a.end(); ){ putchar(' '); print(*i); } }
template<class T, class L> void print(const pair<T, L>& p){ print(p.first); putchar(' '); print(p.second); }
template<class T, size_t size> void print(const T (&a)[size]){ print(a[0]); for(auto i = a; ++i != end(a); ){ putchar(' '); print(*i); } }
template<class T> void print(const T& a){ cout << a; }
int out(){ putchar('\n'); return 0; }
template<class T> int out(const T& t){ print(t); putchar('\n'); return 0; }
template<class Head, class... Tail> int out(const Head& head, const Tail&... tail){ print(head); putchar(' '); out(tail...); return 0; }
#define LL(...) ll __VA_ARGS__; in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__; in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__; in(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__; in(__VA_ARGS__)
#define VEC(type,name,size) vector<type> name(size); in(name)
#define VV(type, name, h, w) vector<vector<type>> name(h, vector<type>(w)); in(name)
#define bit(n,k) (((ll)n>>(ll)k)&1) /*nのk bit目*/
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define eb emplace_back
#define endl '\n'
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define debug(v) cout<<#v<<":";for(auto x:v){cout<<x<<' ';}cout<<endl;
#define pi 3.14159265359
const double eps = 1e-12;
const long long INF= (long long)1e18+20;
const int inf= 1010101010;
typedef long double D;      // 座標値の型。doubleかlong doubleを想定
typedef complex<D> Point;  // Point
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl>vvl;
typedef vector<vvl>vvvl;
typedef vector<vvvl>vvvvl;
typedef vector<vvvvl>vvvvvl;
typedef vector<int>vi;
typedef vector<vi>vvi;
typedef vector<vvi>vvvi;
typedef vector<vvvi>vvvvi;
typedef vector<vvvvi>vvvvvi;
typedef pair<ll,ll> P;
#define __builtin_popcount __builtin_popcountll
// typedef double D;    
template<class T> using minpq=priority_queue<T,vector<T>,greater<T>>;
// const ll MOD=1000000007LL;
const ll MOD=998244353LL;
// using mint=modint998244353;
// using mint=modint1000000007;
// using mint=modint;
// typedef vector<mint> vm;
// typedef vector<vector<mint> >vvm;
// typedef vector<vector<vector<mint> > >vvvm;
//上下右左
vl dx={-1,1,0,0,1,1,-1,-1};
vl dy={0,-0,1,-1,-1,1,-1,1};


template<class T> vector<T> make_vec(size_t a) { return vector<T>(a); }
template<class T, class... Ts> auto make_vec(size_t a, Ts... ts) {
  return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}

template<class T>bool chmax(T &a,const T &b){if(a<b){a=b;return true;}return false;}
template<class T>bool chmin(T &a,const T &b){if(b<a){a=b;return true;}return false;}
template<class T> ll sum(const T& a){ return accumulate(all(a), 0LL); }
template<class T> auto min(const T& a){ return *min_element(all(a)); }
template<class T> auto max(const T& a){ return *max_element(all(a)); }

//素因数分解O(√n)
map<ll,ll>prime_factor(ll n){
  map<ll,ll>res;
  for(ll i=2;i*i<=n;i++){
    while(n%i==0){
      res[i]++;
      n/=i;
    }
  }
  if(n!=1)res[n]=1;
  return res;
}

const ll MAX = 5000010;//5*10^6
long long fac[MAX], finv[MAX], inv[MAX];
//finvが階乗の逆元

// テーブルを作る前処理
void COMinit() {
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    for (ll i = 2; i < MAX; i++){
        fac[i] = fac[i - 1] * i % MOD;
        inv[i] = MOD - inv[MOD%i] * (MOD / i) % MOD;
        finv[i] = finv[i - 1] * inv[i] % MOD;
    }
}

// 二項係数計算
long long COM(ll n, ll k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}


//素数判定O(√n)
bool is_prime(ll n){
  for(ll i=2;i*i<=n;i++){
    if(n%i==0)return false;
  }
  return n!=1;
}

//約数の列挙O(√n)
vector<ll>divisor(ll n){
  vector<ll>res;
  for(ll i=1;i*i<=n;i++){
    if(n%i==0){
      res.push_back(i);
      if(i != n/i) res.push_back(n/i);
    }
  }
  return res;
}


ll exp(ll n,ll r){
    if(r==0)return 1;
    return n*exp(n,r-1);
}

ll factorial(int n){
    if(n==0)return 1;
    return n*factorial(n-1);
}


pair<long long,long long>roop_search(vl next_index,ll first_point){
	ll idx=first_point;
	map<ll,ll>mp;
	mp[idx]=0;
	ll cur=1;
	ll roop_begin=-1;
	ll roop_size=-1;
	while(true){
		idx=next_index[idx];
		if(mp.count(idx)){
			roop_begin=mp[idx];
			roop_size=cur-roop_begin;
			break;
		}
		mp[idx]=cur++;
	}
	return {roop_begin,roop_size};
}


template< typename T >
struct Compress {
  vector< T > xs;

  Compress() = default;

  Compress(const vector< T > &vs) {
    add(vs);
  }

  Compress(const initializer_list< vector< T > > &vs) {
    for(auto &p : vs) add(p);
  }

  void add(const vector< T > &vs) {
    copy(begin(vs), end(vs), back_inserter(xs));
  }

  void add(const T &x) {
    xs.emplace_back(x);
  }

  void build() {
    sort(begin(xs), end(xs));
    xs.erase(unique(begin(xs), end(xs)), end(xs));
  }

  vector< int > get(const vector< T > &vs) const {
    vector< int > ret;
    transform(begin(vs), end(vs), back_inserter(ret), [&](const T &x) {
      return lower_bound(begin(xs), end(xs), x) - begin(xs);
    });
    return ret;
  }

  int get(const T &x) const {
    return lower_bound(begin(xs), end(xs), x) - begin(xs);
  }

  const T &operator[](int k) const {
    return xs[k];
  }
};


template<class T>
void rotate90(ll &h,ll &w,vector<vector<T>>&vec){
    vector<vector<T>>vec2(w,vector<T>(h));
    for(int i=0;i<h;i++){
        for(int j=0;j<w;j++){
            vec2[j][h-1-i]=vec[i][j];
        }
    }
    vec=vec2;
    swap(h,w);
}

struct RandomNumberGenerator {
  mt19937 mt;

  RandomNumberGenerator() : mt(chrono::steady_clock::now().time_since_epoch().count()) {}

  int operator()(int a, int b) { // [a, b)
    uniform_int_distribution< int > dist(a, b - 1);
    return dist(mt);
  }

  int operator()(int b) { // [0, b)
    return (*this)(0, b);
  }
};



int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cout << fixed << setprecision(12);
    //主客転倒！二重和のときは一番内側の物が何回使われるか
    //√Nで分けるテク
    //絶対値は外して2通りの式にした後、変数ごとにまとめる
    //組み合わせが少ないそうなものはdfsで実行してみる（典型25）
    //DはDPのD
    //pow_mod,prime_factor,divisor,is_prime
    // g++ -fsanitize=undefined code.cpp -I.
    // valgrind ./a.out
    /*--------------------------------*/

    ll n,q;cin>>n>>q;
    vl a(n);
    rep(i,n)cin>>a[i];
    
    ll b=ceil(sqrt(n));//パケットのサイズ
    ll cnt=(n+b-1)/b;//パケットの個数
    
    vector<tuple<ll,ll,ll>>vec(cnt,{INF,-INF,0});//遅延評価するminmaxadd
    vvl sort_vec(cnt);//パケットごとにソート
    rep(i,n){
        sort_vec[i/b].pb(a[i]);
    }
    rep(i,b)sort(all(sort_vec));
    
    //両端の愚直更新
    auto f=[&](ll l,ll r,ll c1,ll b1,ll a1)->void{
        //l,rの属するパケットを遅延評価
        ll num=r/b;//numがパケットの番号
        ll dmin,dmax,dadd;
        tie(dmin,dmax,dadd)=vec[num];
        for(ll i=num*b;i<(num+1)*b;i++){
            a[i]+=dadd;
            chmax(a[i],dmax);        
            chmin(a[i],dmin);        
        }
        vec[num]={INF,-INF,0};
        for(ll i=l;i<=r;i++){
            a[i]+=a1;
            chmax(a[i],b1);
            chmin(a[i],c1);
        }
        vl new_sort_vec;
        for(ll i=num*b;i<(num+1)*b;i++){
            new_sort_vec.pb(a[i]);
        }
        sort(all(new_sort_vec));
        sort_vec[num]=new_sort_vec;
    };

    //パケット更新
    auto f2=[&](ll num,ll c2,ll b2,ll a2)->void{
        //numはパケット番号
        ll c1,b1,a1;
        tie(c1,b1,a1)=vec[num];
        ll na=a1+a2;
        ll nb=max(b2,min(c1+a2,b1+a2));
        ll nc=min(c2,max(b2,c1+a2));
        vec[num]={nc,nb,na};
    };

    //両端の愚直取得
    auto f3=[&](ll l,ll r,ll x)->ll {
        //l,rの属するパケットを遅延評価
        ll num=r/b;//numがパケットの番号
        ll dmin,dmax,dadd;
        tie(dmin,dmax,dadd)=vec[num];
        for(ll i=num*b;i<(num+1)*b;i++){
            a[i]+=dadd;
            chmax(a[i],dmax);        
            chmin(a[i],dmin);        
        }
        // if(l==8 and r==9 and (x==-10||x==1)){
            // cout<<"OK"<<endl;
            // cout<<a[8]<<" "<<a[9]<<endl;
        // }

        vec[num]={INF,-INF,0};
        vl new_sort_vec;
        for(ll i=num*b;i<(num+1)*b;i++){
            new_sort_vec.pb(a[i]);
        }
        sort(all(new_sort_vec));
        sort_vec[num]=new_sort_vec;
        
        //x以上の個数を取得
        
        ll res=0;
        for(ll i=l;i<=r;i++){
            if(a[i]>=x)res++;
        }
        return res;
    };
    
    //パケット取得
    auto f4=[&](ll num,ll x)->ll{
        //パケット番号numにおいて、x以上の個数
        ll c1,b1,a1;
        tie(c1,b1,a1)=vec[num];
        if(x>c1)return 0;
        if(x<=b1)return sort_vec[num].size();
        ll nx=x-a1;
        //sort_vecの中でnx以上の個数を求めればよい
        ll res=sort_vec[num].size();
        res-=lower_bound(all(sort_vec[num]),nx)-sort_vec[num].begin();
        return res;
    };

    while(q--){
        ll t;cin>>t;
        // debug(a);
        if(t==1){
            //chminクエリ
            ll l,r,x;cin>>l>>r>>x;
            l--;r--;
            if(l%b!=0){
                //左端愚直更新発生
                if((l+b-1)/b*b-1<=r){
                    f(l,(l+b-1)/b*b-1,x,-INF,0);
                    l=(l+b-1)/b*b;
                }
                else {
                    f(l,r,x,-INF,0);
                    l=r+1;
                }
            }
            if(r%b!=b-1){
                //右端愚直更新発生
                if(l<=r/b*b)f(r/b*b,r,x,-INF,0);
                r=r/b*b-1;
            }
            if(l<=r){
                for(ll i=l/b;i<=r/b;i++){
                    //パケット更新
                    f2(i,x,-INF,0);
                }
            }
        }
        if(t==2){
            //chmaxクエリ
            ll l,r,x;cin>>l>>r>>x;
            l--;r--;
            
            if(l%b!=0){
                //左端愚直更新発生
                if((l+b-1)/b*b-1<=r){
                    f(l,(l+b-1)/b*b-1,INF,x,0);
                    l=(l+b-1)/b*b;
                }
                else {
                    f(l,r,INF,x,0);
                    l=r+1;
                }
            }
            // if(check)cout<<l<<" "<<r<<endl;
            if(r%b!=b-1){
                //右端愚直更新発生
                if(l<=r/b*b)f(r/b*b,r,INF,x,0);
                r=r/b*b-1;
            }
            // if(check)cout<<l<<" "<<r<<endl;
            if(l<=r){
                for(ll i=l/b;i<=r/b;i++){
                    //パケット更新
                    f2(i,INF,x,0);
                }
            }
            // if(check)cout<<l<<" "<<r<<endl;
        }
        if(t==3){
            //addクエリ
            ll l,r,x;cin>>l>>r>>x;
            l--;r--;
            if(l%b!=0){
                //左端愚直更新発生
                if((l+b-1)/b*b-1<=r){
                    f(l,(l+b-1)/b*b-1,INF,-INF,x);
                    l=(l+b-1)/b*b;
                }
                else {
                    f(l,r,INF,-INF,x);
                    l=r+1;
                }
            }
            if(r%b!=b-1){
                //右端愚直更新発生
                if(l<=r/b*b)f(r/b*b,r,INF,-INF,x);
                r=r/b*b-1;
            }
            if(l<=r){
                for(ll i=l/b;i<=r/b;i++){
                    //パケット更新
                    f2(i,INF,-INF,x);
                }
            }
        }
        if(t==4){
            //取得クエリ
            ll l,r,x,y;cin>>l>>r>>x>>y;
            l--;r--;
            bool check=false;
            if(r==8){
                check=true;
                // debug(a);
            }
            // cout<<b<<endl;
            ll ans=0;
            if(l%b!=0){
                //左端愚直更新発生
                //x以上からy+1以上を引けばよい
                if((l+b-1)/b*b-1<=r){
                    ans+=f3(l,(l+b-1)/b*b-1,x);
                    ans-=f3(l,(l+b-1)/b*b-1,y+1);
                    l=(l+b-1)/b*b;
                }
                else {
                    ans+=f3(l,r,x);
                    ans-=f3(l,r,y+1);
                    l=r+1;
                }
            }
            // if(check)cout<<ans<<" "<<l<<" "<<r<<endl;
            if(r%b!=b-1){
                //右端愚直更新発生
                if(l<=r/b*b){
                    ans+=f3(r/b*b,r,x);
                    //引く方がホントは1になるはず
                    // cout<<f3(r/b*b,r,x)<<" "<<f3(r/b*b,r,y+1)<<endl;
                    ans-=f3(r/b*b,r,y+1);
                }
                r=r/b*b-1;
            }
            // if(check)cout<<ans<<" "<<l<<" "<<r<<endl;
            
            // if(l>r){
                // cout<<ans<<endl;
                // continue;
            // }
            // cout<<ans<<" "<<l<<" "<<r<<endl;
            if(l<=r){
                for(ll i=l/b;i<=r/b;i++){
                    //パケット更新
                    // if(l==0 and r==7){
                        // cout<<"OK"<<endl;
                        
                    // }
                    // if(check)cout<<i<<endl;
                    ans+=f4(i,x);
                    // cout<<ans<<endl;
                    ans-=f4(i,y+1);
                    // cout<<ans<<endl;
                }
            }
            cout<<ans<<endl;
        }
        // debug(a);
        // cout<<get<0>(vec[0])<<" "<<get<1>(vec[0])<<" "<<get<2>(vec[0])<<endl;
        // debug(a);
    }

}
accuracy: 0.09523809523809523
time_ms: 140
memory_kb: 5152
final_rank: 16

code_snippet: #line 1 "test/aizu-online-judge/3170.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3170"

#include <algorithm>
#include <cstdio>

#line 2 "src/data_structure/buckets.hpp"

/**
 * @file buckets.hpp
 * @brief Buckets
 */

#include <cmath>
#include <vector>

namespace workspace {

/**
 * @brief Buckets on a sequence.
 */
template <class _Iterator, class _Pack, class _Unpack> struct buckets {
  // Require random access.
  static_assert(
      std::is_same<typename std::iterator_traits<_Iterator>::iterator_category,
                   std::random_access_iterator_tag>::value);

  using difference_type =
      typename std::iterator_traits<_Iterator>::difference_type;

  _Iterator __begin, __end;

  using value_type = decltype(std::declval<_Pack>()(std::declval<_Iterator>(),
                                                    std::declval<_Iterator>()));

  struct bucket {
    value_type __data;
    _Iterator __begin;
    _Iterator __end;
  };

  _Pack __pack;
  _Unpack __unpack;
  difference_type __unit;
  std::vector<bucket> __buckets;

  void prepare() {
    if (!__unit) __unit = round(sqrt(std::distance(__begin, __end)));

    for (auto __l = __begin, __r = __l; __r != __end; __l = __r) {
      for (auto __n = __unit; __r != __end && __n; --__n) ++__r;
      __buckets.push_back({__pack(__l, __r), __l, __r});
    }
  }

 public:
  /**
   * @brief Constuct a new buckets object.
   */
  buckets(_Iterator __first, _Iterator __last, _Pack __pack, _Unpack __unpack,
          difference_type __unit = 0)
      : __begin(__first),
        __end(__last),
        __pack(__pack),
        __unpack(__unpack),
        __unit(__unit) {
    prepare();
  }

  /**
   * @brief Number of buckets.
   */
  auto size() const { return __buckets.size(); }

  bool empty() const { return __begin == __end; }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __first
   * @param __last
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __first, _Iterator __last, _Operator __oper) {
    if (__first == __last) return;

    auto __index = std::distance(__begin, __first);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    if (__index % __unit) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __mid = std::distance(__last, __b->__end) > 0 ? __last : __b->__end;

      auto __tmp = __pack(__first, __mid);
      __oper(__tmp);
      __unpack(__tmp, __first, __mid);

      __b->__data = __pack(__b->__begin, __b->__end);
      ++__b;
    }

    while (true) {
      if (__b == __buckets.end()) return;
      if (std::distance(__b->__end, __last) < 0) break;

      __oper(__b->__data);
      ++__b;
    }

    if (std::distance(__b->__begin, __last) > 0) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __tmp = __pack(__b->__begin, __last);
      __oper(__tmp);
      __unpack(__tmp, __b->__begin, __last);

      __b->__data = __pack(__b->__begin, __b->__end);
    }
  }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __i
   * @param __j
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, difference_type __j, _Operator __oper) {
    operator()(std::next(__begin, __i), std::next(__begin, __j), __oper);
  }
};

}  // namespace workspace
#line 7 "test/aizu-online-judge/3170.test.cpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add;
    std::vector<i64> v;
  };

  constexpr auto inf = __INT64_MAX__;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.min = inf;
        d.max = -inf;
        d.v = std::vector(l, r);
        sort(d.v.begin(), d.v.end());
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      },
      128);

  for (int t, l, r; q--;) {
    i64 x, y;
    scanf("%d%d%d%lld", &t, &l, &r, &x);
    --l;

    switch (--t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
        });
        break;

      case 2:
        b(l, r, [&](auto& d) { d.add += x; });
        break;

      case 3:
        scanf("%lld", &y);
        int num = 0;
        b(l, r, [&](const auto& d) {
          int sign = 1;
          for (auto z : {x - 1 - d.add, y - d.add}) {
            sign *= -1;
            if (z < d.max) continue;
            if (z < d.min)
              num += sign * (std::upper_bound(d.v.begin(), d.v.end(), z) -
                             d.v.begin());
            else
              num += sign * (int)d.v.size();
          }
        });
        printf("%d\n", num);
        break;
    }
  }
}
accuracy: 1
time_ms: 1200
memory_kb: 4160
final_rank: 3

code_snippet: #line 1 "test/aizu-online-judge/3170.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3170"

#include <algorithm>
#include <cstdio>

#line 2 "src/data_structure/buckets.hpp"

/**
 * @file buckets.hpp
 * @brief Buckets
 */

#include <cmath>
#include <vector>

namespace workspace {

/**
 * @brief Buckets on a sequence.
 */
template <class _Iterator, class _Pack, class _Unpack> struct buckets {
  // Require random access.
  static_assert(
      std::is_same<typename std::iterator_traits<_Iterator>::iterator_category,
                   std::random_access_iterator_tag>::value);

  using difference_type =
      typename std::iterator_traits<_Iterator>::difference_type;

  _Iterator __begin, __end;

  using value_type = decltype(std::declval<_Pack>()(std::declval<_Iterator>(),
                                                    std::declval<_Iterator>()));

  struct bucket {
    value_type __data;
    _Iterator __begin;
    _Iterator __end;
  };

  _Pack __pack;
  _Unpack __unpack;
  difference_type __unit;
  std::vector<bucket> __buckets;

  void prepare() {
    if (!__unit) __unit = round(sqrt(std::distance(__begin, __end)));

    for (auto __l = __begin, __r = __l; __r != __end; __l = __r) {
      for (auto __n = __unit; __r != __end && __n; --__n) ++__r;
      __buckets.push_back({__pack(__l, __r), __l, __r});
    }
  }

 public:
  /**
   * @brief Constuct a new buckets object.
   */
  buckets(_Iterator __first, _Iterator __last, _Pack __pack, _Unpack __unpack,
          difference_type __unit = 0)
      : __begin(__first),
        __end(__last),
        __pack(__pack),
        __unpack(__unpack),
        __unit(__unit) {
    prepare();
  }

  /**
   * @brief Number of buckets.
   */
  auto size() const { return __buckets.size(); }

  bool empty() const { return __begin == __end; }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __first
   * @param __last
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __first, _Iterator __last, _Operator __oper) {
    if (__first == __last) return;

    auto __index = std::distance(__begin, __first);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    if (__index % __unit) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __mid = std::distance(__last, __b->__end) > 0 ? __last : __b->__end;

      auto __tmp = __pack(__first, __mid);
      __oper(__tmp);
      __unpack(__tmp, __first, __mid);

      __b->__data = __pack(__b->__begin, __b->__end);
      ++__b;
    }

    while (true) {
      if (__b == __buckets.end()) return;
      if (std::distance(__b->__end, __last) < 0) break;

      __oper(__b->__data);
      ++__b;
    }

    if (std::distance(__b->__begin, __last) > 0) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __tmp = __pack(__b->__begin, __last);
      __oper(__tmp);
      __unpack(__tmp, __b->__begin, __last);

      __b->__data = __pack(__b->__begin, __b->__end);
    }
  }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __i
   * @param __j
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, difference_type __j, _Operator __oper) {
    operator()(std::next(__begin, __i), std::next(__begin, __j), __oper);
  }
};

}  // namespace workspace
#line 7 "test/aizu-online-judge/3170.test.cpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add;
    std::vector<i64> v;
  };

  constexpr auto inf = __INT64_MAX__;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.min = inf;
        d.max = -inf;
        d.v = std::vector(l, r);
        sort(d.v.begin(), d.v.end());
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      },
      100);

  for (int t, l, r; q--;) {
    i64 x, y;
    scanf("%d%d%d%lld", &t, &l, &r, &x);
    --l;

    switch (--t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
        });
        break;

      case 2:
        b(l, r, [&](auto& d) { d.add += x; });
        break;

      case 3:
        scanf("%lld", &y);
        int num = 0;
        b(l, r, [&](const auto& d) {
          int sign = 1;
          for (auto z : {x - 1 - d.add, y - d.add}) {
            sign *= -1;
            if (z < d.max) continue;
            if (z < d.min)
              num += sign * (std::upper_bound(d.v.begin(), d.v.end(), z) -
                             d.v.begin());
            else
              num += sign * (int)d.v.size();
          }
        });
        printf("%d\n", num);
        break;
    }
  }
}
accuracy: 1
time_ms: 1090
memory_kb: 4196
final_rank: 2

code_snippet: #line 1 "test/aizu-online-judge/3170.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3170"

#include <algorithm>
#include <cstdio>

#line 2 "src/data_structure/buckets.hpp"

/**
 * @file buckets.hpp
 * @brief Buckets
 */

#include <cmath>
#include <vector>

namespace workspace {

/**
 * @brief Buckets on a sequence.
 */
template <class _Iterator, class _Pack, class _Unpack> struct buckets {
  // Require random access.
  static_assert(
      std::is_same<typename std::iterator_traits<_Iterator>::iterator_category,
                   std::random_access_iterator_tag>::value);

  using difference_type =
      typename std::iterator_traits<_Iterator>::difference_type;

  _Iterator __begin, __end;

  using value_type = decltype(std::declval<_Pack>()(std::declval<_Iterator>(),
                                                    std::declval<_Iterator>()));

  struct bucket {
    value_type __data;
    _Iterator __begin;
    _Iterator __end;
  };

  _Pack __pack;
  _Unpack __unpack;
  difference_type __unit;
  std::vector<bucket> __buckets;

  void prepare() {
    if (!__unit) __unit = round(sqrt(std::distance(__begin, __end)));

    for (auto __l = __begin, __r = __l; __r != __end; __l = __r) {
      for (auto __n = __unit; __r != __end && __n; --__n) ++__r;
      __buckets.push_back({__pack(__l, __r), __l, __r});
    }
  }

 public:
  /**
   * @brief Constuct a new buckets object.
   */
  buckets(_Iterator __first, _Iterator __last, _Pack __pack, _Unpack __unpack,
          difference_type __unit = 0)
      : __begin(__first),
        __end(__last),
        __pack(__pack),
        __unpack(__unpack),
        __unit(__unit) {
    prepare();
  }

  /**
   * @brief Number of buckets.
   */
  auto size() const { return __buckets.size(); }

  bool empty() const { return __begin == __end; }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __first
   * @param __last
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __first, _Iterator __last, _Operator __oper) {
    if (__first == __last) return;

    auto __index = std::distance(__begin, __first);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    if (__index % __unit) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __mid = std::distance(__last, __b->__end) > 0 ? __last : __b->__end;

      auto __tmp = __pack(__first, __mid);
      __oper(__tmp);
      __unpack(__tmp, __first, __mid);

      __b->__data = __pack(__b->__begin, __b->__end);
      ++__b;
    }

    while (true) {
      if (__b == __buckets.end()) return;
      if (std::distance(__b->__end, __last) < 0) break;

      __oper(__b->__data);
      ++__b;
    }

    if (std::distance(__b->__begin, __last) > 0) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __tmp = __pack(__b->__begin, __last);
      __oper(__tmp);
      __unpack(__tmp, __b->__begin, __last);

      __b->__data = __pack(__b->__begin, __b->__end);
    }
  }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __i
   * @param __j
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, difference_type __j, _Operator __oper) {
    operator()(std::next(__begin, __i), std::next(__begin, __j), __oper);
  }
};

}  // namespace workspace
#line 7 "test/aizu-online-judge/3170.test.cpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add;
    std::vector<i64> v;
  };

  constexpr auto inf = __INT64_MAX__;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.min = inf;
        d.max = -inf;
        d.v = std::vector(l, r);
        sort(d.v.begin(), d.v.end());
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      },
      30);

  for (int t, l, r; q--;) {
    i64 x, y;
    scanf("%d%d%d%lld", &t, &l, &r, &x);
    --l;

    switch (--t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
        });
        break;

      case 2:
        b(l, r, [&](auto& d) { d.add += x; });
        break;

      case 3:
        scanf("%lld", &y);
        int num = 0;
        b(l, r, [&](const auto& d) {
          int sign = 1;
          for (auto z : {x - 1 - d.add, y - d.add}) {
            sign *= -1;
            if (z < d.max) continue;
            if (z < d.min)
              num += sign * (std::upper_bound(d.v.begin(), d.v.end(), z) -
                             d.v.begin());
            else
              num += sign * (int)d.v.size();
          }
        });
        printf("%d\n", num);
        break;
    }
  }
}
accuracy: 1
time_ms: 1210
memory_kb: 4404
final_rank: 4

code_snippet: #line 1 "test/aizu-online-judge/3170.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3170"

#include <algorithm>
#include <cstdio>

#line 2 "src/data_structure/buckets.hpp"

/**
 * @file buckets.hpp
 * @brief Buckets
 */

#include <cmath>
#include <vector>

namespace workspace {

/**
 * @brief Buckets on a sequence.
 */
template <class _Iterator, class _Pack, class _Unpack> struct buckets {
  // Require random access.
  static_assert(
      std::is_same<typename std::iterator_traits<_Iterator>::iterator_category,
                   std::random_access_iterator_tag>::value);

  using difference_type =
      typename std::iterator_traits<_Iterator>::difference_type;

  _Iterator __begin, __end;

  using value_type = decltype(std::declval<_Pack>()(std::declval<_Iterator>(),
                                                    std::declval<_Iterator>()));

  struct bucket {
    value_type __data;
    _Iterator __begin;
    _Iterator __end;
  };

  _Pack __pack;
  _Unpack __unpack;
  difference_type __unit;
  std::vector<bucket> __buckets;

  void prepare() {
    if (!__unit) __unit = round(sqrt(std::distance(__begin, __end)));

    for (auto __l = __begin, __r = __l; __r != __end; __l = __r) {
      for (auto __n = __unit; __r != __end && __n; --__n) ++__r;
      __buckets.push_back({__pack(__l, __r), __l, __r});
    }
  }

 public:
  /**
   * @brief Constuct a new buckets object.
   */
  buckets(_Iterator __first, _Iterator __last, _Pack __pack, _Unpack __unpack,
          difference_type __unit = 0)
      : __begin(__first),
        __end(__last),
        __pack(__pack),
        __unpack(__unpack),
        __unit(__unit) {
    prepare();
  }

  /**
   * @brief Number of buckets.
   */
  auto size() const { return __buckets.size(); }

  bool empty() const { return __begin == __end; }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __first
   * @param __last
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __first, _Iterator __last, _Operator __oper) {
    if (__first == __last) return;

    auto __index = std::distance(__begin, __first);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    if (__index % __unit) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __mid = std::distance(__last, __b->__end) > 0 ? __last : __b->__end;

      auto __tmp = __pack(__first, __mid);
      __oper(__tmp);
      __unpack(__tmp, __first, __mid);

      __b->__data = __pack(__b->__begin, __b->__end);
      ++__b;
    }

    while (true) {
      if (__b == __buckets.end()) return;
      if (std::distance(__b->__end, __last) < 0) break;

      __oper(__b->__data);
      ++__b;
    }

    if (std::distance(__b->__begin, __last) > 0) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __tmp = __pack(__b->__begin, __last);
      __oper(__tmp);
      __unpack(__tmp, __b->__begin, __last);

      __b->__data = __pack(__b->__begin, __b->__end);
    }
  }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __i
   * @param __j
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, difference_type __j, _Operator __oper) {
    operator()(std::next(__begin, __i), std::next(__begin, __j), __oper);
  }
};

}  // namespace workspace
#line 7 "test/aizu-online-judge/3170.test.cpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add;
    std::vector<i64> v;
  };

  constexpr auto inf = __INT64_MAX__;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.min = inf;
        d.max = -inf;
        d.v = std::vector(l, r);
        sort(d.v.begin(), d.v.end());
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      },
      50);

  for (int t, l, r; q--;) {
    i64 x, y;
    scanf("%d%d%d%lld", &t, &l, &r, &x);
    --l;

    switch (--t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
        });
        break;

      case 2:
        b(l, r, [&](auto& d) { d.add += x; });
        break;

      case 3:
        scanf("%lld", &y);
        int num = 0;
        b(l, r, [&](const auto& d) {
          int sign = 1;
          for (auto z : {x - 1 - d.add, y - d.add}) {
            sign *= -1;
            if (z < d.max) continue;
            if (z < d.min)
              num += sign * (std::upper_bound(d.v.begin(), d.v.end(), z) -
                             d.v.begin());
            else
              num += sign * (int)d.v.size();
          }
        });
        printf("%d\n", num);
        break;
    }
  }
}
accuracy: 1
time_ms: 990
memory_kb: 4384
final_rank: 1

code_snippet: #line 1 "test/aizu-online-judge/3170.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3170"

#include <algorithm>
#include <cstdio>

#line 2 "src/data_structure/buckets.hpp"

/**
 * @file buckets.hpp
 * @brief Buckets
 */

#include <cmath>
#include <vector>

namespace workspace {

/**
 * @brief Buckets on a sequence.
 */
template <class _Iterator, class _Pack, class _Unpack> struct buckets {
  // Require random access.
  static_assert(
      std::is_same<typename std::iterator_traits<_Iterator>::iterator_category,
                   std::random_access_iterator_tag>::value);

  using difference_type =
      typename std::iterator_traits<_Iterator>::difference_type;

  _Iterator __begin, __end;

  using value_type = decltype(std::declval<_Pack>()(std::declval<_Iterator>(),
                                                    std::declval<_Iterator>()));

  struct bucket {
    value_type __data;
    _Iterator __begin;
    _Iterator __end;
  };

  _Pack __pack;
  _Unpack __unpack;
  difference_type __unit;
  std::vector<bucket> __buckets;

  void prepare() {
    if (!__unit) __unit = round(sqrt(std::distance(__begin, __end)));

    for (auto __l = __begin, __r = __l; __r != __end; __l = __r) {
      for (auto __n = __unit; __r != __end && __n; --__n) ++__r;
      __buckets.push_back({__pack(__l, __r), __l, __r});
    }
  }

 public:
  /**
   * @brief Constuct a new buckets object.
   */
  buckets(_Iterator __first, _Iterator __last, _Pack __pack, _Unpack __unpack,
          difference_type __unit = 0)
      : __begin(__first),
        __end(__last),
        __pack(__pack),
        __unpack(__unpack),
        __unit(__unit) {
    prepare();
  }

  /**
   * @brief Number of buckets.
   */
  auto size() const { return __buckets.size(); }

  bool empty() const { return __begin == __end; }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __first
   * @param __last
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __first, _Iterator __last, _Operator __oper) {
    if (__first == __last) return;

    auto __index = std::distance(__begin, __first);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    if (__index % __unit) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __mid = std::distance(__last, __b->__end) > 0 ? __last : __b->__end;

      auto __tmp = __pack(__first, __mid);
      __oper(__tmp);
      __unpack(__tmp, __first, __mid);

      __b->__data = __pack(__b->__begin, __b->__end);
      ++__b;
    }

    while (true) {
      if (__b == __buckets.end()) return;
      if (std::distance(__b->__end, __last) < 0) break;

      __oper(__b->__data);
      ++__b;
    }

    if (std::distance(__b->__begin, __last) > 0) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __tmp = __pack(__b->__begin, __last);
      __oper(__tmp);
      __unpack(__tmp, __b->__begin, __last);

      __b->__data = __pack(__b->__begin, __b->__end);
    }
  }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __i
   * @param __j
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, difference_type __j, _Operator __oper) {
    operator()(std::next(__begin, __i), std::next(__begin, __j), __oper);
  }
};

}  // namespace workspace
#line 7 "test/aizu-online-judge/3170.test.cpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add;
    std::vector<i64> v;
  };

  constexpr auto inf = __INT64_MAX__;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.min = inf;
        d.max = -inf;
        d.v = std::vector(l, r);
        sort(d.v.begin(), d.v.end());
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      },
      150);

  for (int t, l, r; q--;) {
    i64 x, y;
    scanf("%d%d%d%lld", &t, &l, &r, &x);
    --l;

    switch (--t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
        });
        break;

      case 2:
        b(l, r, [&](auto& d) { d.add += x; });
        break;

      case 3:
        scanf("%lld", &y);
        int num = 0;
        b(l, r, [&](const auto& d) {
          int sign = 1;
          for (auto z : {x - 1 - d.add, y - d.add}) {
            sign *= -1;
            if (z < d.max) continue;
            if (z < d.min)
              num += sign * (std::upper_bound(d.v.begin(), d.v.end(), z) -
                             d.v.begin());
            else
              num += sign * (int)d.v.size();
          }
        });
        printf("%d\n", num);
        break;
    }
  }
}
accuracy: 1
time_ms: 1350
memory_kb: 4196
final_rank: 9

code_snippet: #line 1 "test/aizu-online-judge/3170.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/3170"

#include <algorithm>
#include <cstdio>

#line 2 "src/data_structure/buckets.hpp"

/**
 * @file buckets.hpp
 * @brief Buckets
 */

#include <cmath>
#include <vector>

namespace workspace {

/**
 * @brief Buckets on a sequence.
 */
template <class _Iterator, class _Pack, class _Unpack> struct buckets {
  // Require random access.
  static_assert(
      std::is_same<typename std::iterator_traits<_Iterator>::iterator_category,
                   std::random_access_iterator_tag>::value);

  using difference_type =
      typename std::iterator_traits<_Iterator>::difference_type;

  _Iterator __begin, __end;

  using value_type = decltype(std::declval<_Pack>()(std::declval<_Iterator>(),
                                                    std::declval<_Iterator>()));

  struct bucket {
    value_type __data;
    _Iterator __begin;
    _Iterator __end;
  };

  _Pack __pack;
  _Unpack __unpack;
  difference_type __unit;
  std::vector<bucket> __buckets;

  void prepare() {
    if (!__unit) __unit = round(sqrt(std::distance(__begin, __end)));

    for (auto __l = __begin, __r = __l; __r != __end; __l = __r) {
      for (auto __n = __unit; __r != __end && __n; --__n) ++__r;
      __buckets.push_back({__pack(__l, __r), __l, __r});
    }
  }

 public:
  /**
   * @brief Constuct a new buckets object.
   */
  buckets(_Iterator __first, _Iterator __last, _Pack __pack, _Unpack __unpack,
          difference_type __unit = 0)
      : __begin(__first),
        __end(__last),
        __pack(__pack),
        __unpack(__unpack),
        __unit(__unit) {
    prepare();
  }

  /**
   * @brief Number of buckets.
   */
  auto size() const { return __buckets.size(); }

  bool empty() const { return __begin == __end; }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __first
   * @param __last
   * @param __oper
   */
  template <class _Operator>
  void operator()(_Iterator __first, _Iterator __last, _Operator __oper) {
    if (__first == __last) return;

    auto __index = std::distance(__begin, __first);
    auto __b = std::next(__buckets.begin(), __index / __unit);

    if (__index % __unit) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __mid = std::distance(__last, __b->__end) > 0 ? __last : __b->__end;

      auto __tmp = __pack(__first, __mid);
      __oper(__tmp);
      __unpack(__tmp, __first, __mid);

      __b->__data = __pack(__b->__begin, __b->__end);
      ++__b;
    }

    while (true) {
      if (__b == __buckets.end()) return;
      if (std::distance(__b->__end, __last) < 0) break;

      __oper(__b->__data);
      ++__b;
    }

    if (std::distance(__b->__begin, __last) > 0) {
      __unpack(__b->__data, __b->__begin, __b->__end);

      auto __tmp = __pack(__b->__begin, __last);
      __oper(__tmp);
      __unpack(__tmp, __b->__begin, __last);

      __b->__data = __pack(__b->__begin, __b->__end);
    }
  }

  /**
   * @brief Operate on a subsegment.
   *
   * @param __i
   * @param __j
   * @param __oper
   */
  template <class _Operator>
  void operator()(difference_type __i, difference_type __j, _Operator __oper) {
    operator()(std::next(__begin, __i), std::next(__begin, __j), __oper);
  }
};

}  // namespace workspace
#line 7 "test/aizu-online-judge/3170.test.cpp"

int main() {
  using namespace workspace;
  using i64 = int64_t;

  int n, q;
  scanf("%d%d", &n, &q);
  std::vector<i64> a(n);
  for (auto&& x : a) {
    scanf("%lld", &x);
  }

  struct data {
    i64 min, max, add;
    std::vector<i64> v;
  };

  constexpr auto inf = __INT64_MAX__;

  buckets b(
      begin(a), end(a),
      [](auto l, auto r) {
        data d;
        d.add = 0;
        d.min = inf;
        d.max = -inf;
        d.v = std::vector(l, r);
        sort(d.v.begin(), d.v.end());
        return d;
      },
      [](const auto& d, auto l, auto r) {
        while (l != r) {
          *l = std::min(d.min, std::max(d.max, *l)) + d.add;
          ++l;
        }
      },
      200);

  for (int t, l, r; q--;) {
    i64 x, y;
    scanf("%d%d%d%lld", &t, &l, &r, &x);
    --l;

    switch (--t) {
      case 0:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.min < c) return;
          d.min = c;
          if (d.max > c) d.max = c;
        });
        break;

      case 1:
        b(l, r, [&](auto& d) {
          auto c = x - d.add;
          if (d.max > c) return;
          d.max = c;
          if (d.min < c) d.min = c;
        });
        break;

      case 2:
        b(l, r, [&](auto& d) { d.add += x; });
        break;

      case 3:
        scanf("%lld", &y);
        int num = 0;
        b(l, r, [&](const auto& d) {
          int sign = 1;
          for (auto z : {x - 1 - d.add, y - d.add}) {
            sign *= -1;
            if (z < d.max) continue;
            if (z < d.min)
              num += sign * (std::upper_bound(d.v.begin(), d.v.end(), z) -
                             d.v.begin());
            else
              num += sign * (int)d.v.size();
          }
        });
        printf("%d\n", num);
        break;
    }
  }
}
accuracy: 1
time_ms: 1660
memory_kb: 4432
final_rank: 12

code_snippet: #include <cmath>
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <set>
#include <queue>
#include <string>
#include <map>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
#include <sstream>
#include <bitset>
#include <complex>
#include <chrono>
#include <cassert>
class SqrtSegment {
	int sqrt;
	std::vector<std::vector<std::pair<long long int, int>>> segments;
	std::vector<long long int> min, max, add;
	void change_min_partial(const int from, const int until, const long long int x) {
		const auto added = add[from / sqrt];
		const auto upper_limit = min[from / sqrt];
		const auto lower_limit = max[from / sqrt];
		for (auto& [value, pos] : segments[from / sqrt]) {
			value = std::min(upper_limit, std::max(lower_limit, value));
			value += added;
			if (pos < from || until <= pos) continue;
			value = std::min(value, x);
		}
		std::sort(segments[from / sqrt].begin(), segments[from / sqrt].end());
		add[from / sqrt] = 0;
		min[from / sqrt] = LLONG_MAX;
		max[from / sqrt] = LLONG_MIN;
	}
	void change_max_partial(const int from, const int until, const long long int x) {
		const auto added = add[from / sqrt];
		const auto upper_limit = min[from / sqrt];
		const auto lower_limit = max[from / sqrt];
		for (auto& [value, pos] : segments[from / sqrt]) {
			value = std::min(upper_limit, std::max(lower_limit, value));
			value += added;
			if (pos < from || until <= pos) continue;
			value = std::max(value, x);
		}
		std::sort(segments[from / sqrt].begin(), segments[from / sqrt].end());
		add[from / sqrt] = 0;
		min[from / sqrt] = LLONG_MAX;
		max[from / sqrt] = LLONG_MIN;
	}
	void change_add_partial(const int from, const int until, const long long int x) {
		const auto added = add[from / sqrt];
		const auto upper_limit = min[from / sqrt];
		const auto lower_limit = max[from / sqrt];
		for (auto& [value, pos] : segments[from / sqrt]) {
			value = std::min(upper_limit, std::max(lower_limit, value));
			value += added;
			if (pos < from || until <= pos) continue;
			value += x;
		}
		std::sort(segments[from / sqrt].begin(), segments[from / sqrt].end());
		add[from / sqrt] = 0;
		min[from / sqrt] = LLONG_MAX;
		max[from / sqrt] = LLONG_MIN;
	}
	void change_min_segment(const int segment, const long long int x) {
		min[segment] = std::min(min[segment], x - add[segment]);
	}
	void change_max_segment(const int segment, const long long int x) {
		max[segment] = std::max(max[segment], x - add[segment]);
	}
	void change_add_segment(const int segment, const long long int x) {
		add[segment] += x;
	}
	int count_partial(const int from, const int until, const long long int lower, const long long int upper) {
		int result{ 0 };
		const auto added = add[from / sqrt];
		const auto upper_limit = min[from / sqrt];
		const auto lower_limit = max[from / sqrt];
		for (auto& [value, pos] : segments[from / sqrt]) {
			value = std::min(upper_limit, std::max(lower_limit, value));
			value += added;
			if (pos < from || until <= pos) continue;
			if (lower <= value && value <= upper) ++result;
		}
		add[from / sqrt] = 0;
		min[from / sqrt] = LLONG_MAX;
		max[from / sqrt] = LLONG_MIN;
		return result;
	}
	int count_segment(const int segment, const long long int lower, const long long int upper) {
		const auto upper_limit = std::min(upper - add[segment], min[segment]);
		const auto lower_limit = std::max(lower - add[segment], max[segment]);
		return std::distance(std::lower_bound(segments[segment].begin(), segments[segment].end(), std::make_pair(lower_limit, -1)), std::upper_bound(segments[segment].begin(), segments[segment].end(), std::make_pair(upper_limit, INT_MAX)));
	}

public:
	SqrtSegment(const std::vector<int>& initial) : sqrt{ (int)std::ceil(std::sqrt(initial.size() * std::log2(initial.size()))) }, segments((initial.size() + sqrt - 1) / sqrt), min(segments.size(), LLONG_MAX), max(segments.size(), LLONG_MIN), add(segments.size(), 0) {
		for (auto i = 0; i < segments.size(); ++i) {
			const auto offset = i * sqrt;
			for (auto j = 0; j < sqrt; ++j) {
				if (offset + j >= initial.size()) break;
				segments[i].emplace_back(initial[offset + j], offset + j);
			}
			std::sort(segments[i].begin(), segments[i].end());
		}
	}
	std::vector<long long int> show_value() const {
		std::vector<std::pair<long long int, int>> values;
		for (auto i = 0; i < segments.size(); ++i) {
			const auto added = add[i];
			const auto upper_limit = min[i];
			const auto lower_limit = max[i];
			for (const auto [value, pos]: segments[i]) {
				values.emplace_back(std::max(lower_limit, std::min(upper_limit, value)) + added, pos);
			}
		}
		std::vector<long long int >result(values.size());
		for (const auto [value, pos] : values) {
			result[pos] = value;
		}
		return result;
	}
	void change_min(const int left, const int right, const int x) {
		const auto from = (left + sqrt - 1) / sqrt;
		const auto until = right / sqrt;
		if (from > until) {
			return change_min_partial(left, right + 1, x);
		}
		change_min_partial(left, from * sqrt, x);
		for (auto i = from; i < until; ++i) {
			change_min_segment(i, x);
		}
		change_min_partial(until * sqrt, right + 1, x);
	}
	void change_max(const int left, const int right, const int x) {
		const auto from = (left + sqrt - 1) / sqrt;
		const auto until = right / sqrt;
		if (from > until) {
			return change_max_partial(left, right + 1, x);
		}
		change_max_partial(left, from * sqrt, x);
		for (auto i = from; i < until; ++i) {
			change_max_segment(i, x);
		}
		change_max_partial(until * sqrt, right + 1, x);
	}
	void change_add(const int left, const int right, const int x) {
		const auto from = (left + sqrt - 1) / sqrt;
		const auto until = right / sqrt;
		if (from > until) {
			return change_add_partial(left, right + 1, x);
		}
		change_add_partial(left, from * sqrt, x);
		for (auto i = from; i < until; ++i) {
			change_add_segment(i, x);
		}
		change_add_partial(until * sqrt, right + 1, x);
	}
	int count(const int left, const int right, const long long int x, const long long int y) {
		const auto from = (left + sqrt - 1) / sqrt;
		const auto until = right / sqrt;
		if (from > until) {
			return count_partial(left, right + 1, x, y);
		}
		long long int result{ count_partial(left, from * sqrt, x, y) };
		for (auto i = from; i < until; ++i) {
			result += count_segment(i, x, y);
		}
		result += count_partial(until * sqrt, right + 1, x, y);
		return result;
	}
};

int main() {
	std::cin.tie(nullptr); std::cin.sync_with_stdio(false);
	int n, q; std::cin >> n >> q;
	std::vector<int> initial(n);
	for (auto& a : initial) std::cin >> a;
	SqrtSegment seg(initial);
	for (auto i = 0; i < q; ++i) {
		int type; std::cin >> type;
		if (type == 1) {
			int l, r, x; std::cin >> l >> r >> x; --l; --r;
			seg.change_min(l, r, x);
		}
		else if (type == 2) {
			int l, r, x; std::cin >> l >> r >> x; --l; --r;
			seg.change_max(l, r, x);
		}
		else if (type == 3) {
			int l, r, x; std::cin >> l >> r >> x; --l; --r;
			seg.change_add(l, r, x);
		}
		else {
			int l, r; long long int x, y; std::cin >> l >> r >> x >> y; --l; --r;
			std::cout << seg.count(l, r, x, y) << '\n';
		}
	}
}


/*
https://onlinejudge.u-aizu.ac.jp/challenges/sources/VPC/HUPC/3170




.*/
accuracy: 0.09523809523809523
time_ms: 900
memory_kb: 5164
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

__attribute__((constructor))
void fast_io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
}

template<class S,
         class F,
         S (*mapping)(F, S),
         F (*composition)(F, F),
         F (*id)(),
         class I,
         I (*precalculate)(const vector<S>&),
         class P,
         P (*op)(P, P),
         P (*e)()>
class sqrt_decomposition {
    using Calc_from_S = function<P(S)>;
    using Calc_from_I = function<P(const I&, F, int, int)>;
    
    class bucket {
        int l, r;
        vector<S> vs;
        F lazy_f;
        I info;

        void reflect_apply() {
            if (lazy_f == id()) return;
            for_each(vs.begin(), vs.end(), [&](S& v) { v = mapping(lazy_f, v); });
            lazy_f = id();
        }

        void reflect_prod() {
            info = precalculate(vs);
        }

        void partial_apply(int l, int r, F f) {
            reflect_apply();
            for_each(vs.begin() + l, vs.begin() + r, [&](S& v) { v = mapping(f, v); });
            reflect_prod();
        }

        void all_apply(F f) {
            lazy_f = composition(f, lazy_f);
        }

        P partial_prod(int l, int r, const Calc_from_S& cs) {
            reflect_apply();
            reflect_prod();
            P res = e();
            for_each(vs.begin() + l, vs.begin() + r, [&](S& v) { res = op(res, cs(v)); });
            return res;
        }

        P all_prod(const Calc_from_I& ci) {
            return ci(info, lazy_f, l, r);
        }
        
    public:
        bucket(const vector<S>& a, int l, int r)
            : l(l), r(r), vs(a.begin() + l, a.begin() + r), lazy_f(id()) { reflect_prod(); }

        void apply(int s, int t, F f) {
            if (t <= l || r <= s) return;
            if (s <= l && r <= t) {
                all_apply(f);
            } else {
                partial_apply(max(l, s) - l, min(r, t) - l, f);
            }
        }

        P prod(int s, int t, const Calc_from_S& cs, const Calc_from_I& ci) {
            if (t <= l || r <= s) return e();
            if (s <= l && r <= t) {
                return all_prod(ci);
            } else {
                return partial_prod(max(l, s) - l, min(r, t) - l, cs);
            }
        }
    };

    vector<bucket> bs;

public:
    sqrt_decomposition(const vector<S>& a, int bucket_size) {
        for (int i = 0; i < (int)a.size(); i += bucket_size) {
            bs.emplace_back(a, i, min(i + bucket_size, (int)a.size()));
        }
    }

    void apply(int l, int r, F f) {
        for_each(bs.begin(), bs.end(), [&](bucket& b) { b.apply(l, r, f); });
    }

    P prod(int l, int r, const Calc_from_S& cs, const Calc_from_I& ci) {
        P res = e();
        for_each(bs.begin(), bs.end(), [&](bucket& b) { res = op(res, b.prod(l, r, cs, ci)); });
        return res;
    }
};

using S = long long;
using F = tuple<long long, long long, long long>;
S mapping(F f, S x) {
    auto [chmin, chmax, add] = f;
    x = min(x, chmin);
    x = max(x, chmax);
    x += add;
    return x;
}
F composition(F f, F g) {
    auto [fchmin, fchmax, fadd] = f;
    auto [gchmin, gchmax, gadd] = g;
    long long chmin = min(gchmin, fchmin - gadd);
    long long chmax = max(min(gchmax, fchmin - gadd), fchmax - gadd);
    long long add = gadd + fadd;
    return {chmin, chmax, add};
}
F id() { return {LLONG_MAX / 2, LLONG_MIN / 2, 0}; }
using I = vector<long long>;
I precalculate(const vector<S>& vs) {
    I res = vs;
    sort(res.begin(), res.end());
    return res;
}
using P = int;
P op(P a, P b) { return a + b; }
P e() { return 0; }

int main() {
    int n, q;
    cin >> n >> q;
    vector<S> a(n);
    for (auto& ai : a) cin >> ai;
    sqrt_decomposition<S, F, mapping, composition, id, I, precalculate, P, op, e> sqd(a, 128);

    while (q--) {
        int com, l, r;
        long long x, y;
        cin >> com >> l >> r >> x;
        l--;
        if (com == 4) {
            cin >> y;
            auto cs = [&](S s) { return x <= s && s <= y; };
            auto ci = [&](const I& info, F f, int l, int r) {
                auto [chmin, chmax, add] = f;
                auto calc = [&](long long ub) {
                    if (chmax > ub - add) return 0;
                    if (chmin <= ub - add) return r - l;
                    return (int)distance(info.begin(), upper_bound(info.begin(), info.end(), ub - add));
                };
                return calc(y) - calc(x - 1);
            };
            cout << sqd.prod(l, r, cs, ci) << '\n';
        } else {
            F f = id();
            auto& [chmin, chmax, add] = f;
            if (com == 1) chmin = x;
            if (com == 2) chmax = x;
            if (com == 3) add = x;
            sqd.apply(l, r, f);
        }
    }
}
accuracy: 1
time_ms: 1140
memory_kb: 5648
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

__attribute__((constructor))
void fast_io() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
}

template<class S,
         class F,
         S (*mapping)(F, S),
         F (*composition)(F, F),
         F (*id)(),
         class I,
         I (*precalculate)(const vector<S>&),
         class P,
         P (*op)(P, P),
         P (*e)()>
class sqrt_decomposition {
    using Calc_from_S = function<P(S)>;
    using Calc_from_I = function<P(const I&, const F&, int, int)>;
    
    class bucket {
        int l, r;
        vector<S> vs;
        F lazy_f;
        I info;

        void reflect_apply() {
            if (lazy_f == id()) return;
            for_each(vs.begin(), vs.end(), [&](S& v) { v = mapping(lazy_f, v); });
            lazy_f = id();
        }

        void reflect_prod() {
            info = precalculate(vs);
        }

        void partial_apply(int l, int r, const F& f) {
            reflect_apply();
            for_each(vs.begin() + l, vs.begin() + r, [&](S& v) { v = mapping(f, v); });
            reflect_prod();
        }

        void all_apply(const F& f) {
            lazy_f = composition(f, lazy_f);
        }

        P partial_prod(int l, int r, const Calc_from_S& cs) {
            reflect_apply();
            reflect_prod();
            P res = e();
            for_each(vs.begin() + l, vs.begin() + r, [&](S& v) { res = op(res, cs(v)); });
            return res;
        }

        P all_prod(const Calc_from_I& ci) {
            return ci(info, lazy_f, l, r);
        }
        
    public:
        bucket(const vector<S>& a, int l, int r)
            : l(l), r(r), vs(a.begin() + l, a.begin() + r), lazy_f(id()) { reflect_prod(); }

        void apply(int s, int t, const F& f) {
            if (t <= l || r <= s) return;
            if (s <= l && r <= t) {
                all_apply(f);
            } else {
                partial_apply(max(l, s) - l, min(r, t) - l, f);
            }
        }

        P prod(int s, int t, const Calc_from_S& cs, const Calc_from_I& ci) {
            if (t <= l || r <= s) return e();
            if (s <= l && r <= t) {
                return all_prod(ci);
            } else {
                return partial_prod(max(l, s) - l, min(r, t) - l, cs);
            }
        }
    };

    vector<bucket> bs;

public:
    sqrt_decomposition(const vector<S>& a, int bucket_size) {
        for (int i = 0; i < (int)a.size(); i += bucket_size) {
            bs.emplace_back(a, i, min(i + bucket_size, (int)a.size()));
        }
    }

    void apply(int l, int r, const F& f) {
        for_each(bs.begin(), bs.end(), [&](bucket& b) { b.apply(l, r, f); });
    }

    P prod(int l, int r, const Calc_from_S& cs, const Calc_from_I& ci) {
        P res = e();
        for_each(bs.begin(), bs.end(), [&](bucket& b) { res = op(res, b.prod(l, r, cs, ci)); });
        return res;
    }
};

using S = long long;
using F = tuple<long long, long long, long long>;
S mapping(F f, S x) {
    auto [chmin, chmax, add] = f;
    x = min(x, chmin);
    x = max(x, chmax);
    x += add;
    return x;
}
F composition(F f, F g) {
    auto [fchmin, fchmax, fadd] = f;
    auto [gchmin, gchmax, gadd] = g;
    long long chmin = min(gchmin, fchmin - gadd);
    long long chmax = max(min(gchmax, fchmin - gadd), fchmax - gadd);
    long long add = gadd + fadd;
    return {chmin, chmax, add};
}
F id() { return {LLONG_MAX / 10, LLONG_MIN / 10, 0}; }
using I = vector<long long>;
I precalculate(const vector<S>& vs) {
    I res = vs;
    sort(res.begin(), res.end());
    return res;
}
using P = int;
P op(P a, P b) { return a + b; }
P e() { return 0; }

int main() {
    int n, q;
    cin >> n >> q;
    vector<S> a(n);
    for (auto& ai : a) cin >> ai;
    sqrt_decomposition<S, F, mapping, composition, id, I, precalculate, P, op, e> sqd(a, 256);

    while (q--) {
        int com, l, r;
        long long x, y;
        cin >> com >> l >> r >> x;
        l--;
        if (com == 4) {
            cin >> y;
            auto cs = [&](S s) { return x <= s && s <= y; };
            auto ci = [&](const I& info, const F& f, int l, int r) {
                auto [chmin, chmax, add] = f;
                auto calc = [&](long long border) {
                    if (chmax > border - add) return 0;
                    if (chmin <= border - add) return r - l;
                    return (int)distance(info.begin(), upper_bound(info.begin(), info.end(), border - add));
                };
                return calc(y) - calc(x - 1);
            };
            cout << sqd.prod(l, r, cs, ci) << '\n';
        } else {
            F f = id();
            auto& [chmin, chmax, add] = f;
            if (com == 1) chmin = x;
            if (com == 2) chmax = x;
            if (com == 3) add = x;
            sqd.apply(l, r, f);
        }
    }
}
accuracy: 1
time_ms: 1500
memory_kb: 5492
final_rank: 14

code_snippet: #pragma GCC optimize("Ofast")
#include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
#include <iomanip> // setprecision
#include <complex> // complex
#include <math.h> 
#include <cmath>
#include <functional>
#include <cassert>
using namespace std;
using ll = long long;
using P = pair<ll,ll>;
constexpr ll INF = 1e18;
constexpr int inf = 1e9;
// constexpr ll mod = 1000000007;
constexpr ll mod = 998244353;
const int dx[8] = {1, 0, -1, 0,1,1,-1,-1};
const int dy[8] = {0, 1, 0, -1,1,-1,1,-1};
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
const char eol = '\n';
// --------------------------------------------------------------------------

struct SqrtDecomposition{
  const int sqrtN = 256;
  int N,K;
  vector<ll> data;
  vector<ll> bucketMin;
  vector<ll> bucketMax;
  vector<ll> bucketAdd;
  vector<vector<ll>> sortedBucket;
  SqrtDecomposition(vector<ll> A): data(A){
    N = data.size();
    K = (N + sqrtN - 1)/sqrtN;
    bucketMin.assign(K,INF);
    bucketMax.assign(K,-INF);
    bucketAdd.assign(K,0);
    sortedBucket = vector<vector<ll>>(K);
    for(int k=0; k<K; k++){
      int l = k * sqrtN;
      int r = (k+1) * sqrtN;
      chmin(r,N);
      for(int j=l; j<r; j++){
        sortedBucket[k].emplace_back(data[j]);
      }
      sort(sortedBucket[k].begin(),sortedBucket[k].end());
    }
  }
  void eval(int k){
      int l = k * sqrtN;
      int r = (k+1) * sqrtN;
      chmin(r,N);
      for(int i=l; i<r; i++){
        chmin(data[i],bucketMin[k]);
        chmax(data[i],bucketMax[k]);
        data[i] += bucketAdd[k];
      }
      bucketAdd[k] = 0;
      bucketMin[k] = INF;
      bucketMax[k] = -INF;
  }
  // [s,t)
  void update(int id,int s,int t,ll x){
    for(int k=0; k<K; k++){
      int l = k * sqrtN;
      int r = (k+1) * sqrtN;
      chmin(r,N);
      if(r <= s || t <= l) continue;
      if(s <= l && r <= t){
        if(id == 1){ // min 
          x -= bucketAdd[k];
          chmin(bucketMin[k],x);
          if(bucketMin[k] < bucketMax[k]) bucketMax[k] = bucketMin[k];
          x += bucketAdd[k];
        }else if(id == 2){ // max
          x -= bucketAdd[k];
          chmax(bucketMax[k],x);
          if(bucketMin[k] < bucketMax[k]) bucketMin[k] = bucketMax[k];
          x += bucketAdd[k];
        }else{ // add
          bucketAdd[k] += x;
        }
      }else{
        eval(k);
        for(int i=max(l,s); i<min(r,t); i++){
          if(id == 1) chmin(data[i],x);
          else if(id == 2) chmax(data[i],x);
          else data[i] += x;
        }
        vector<ll> temp;
        for(int i=l; i<r; i++){
          temp.emplace_back(data[i]);
        }
        sort(temp.begin(),temp.end());
        sortedBucket[k] = temp;
      }
    }
  }

  // [s,t) [x,y]
  int query(int s,int t,ll x,ll y){
    int res = 0;
    for(int k=0; k<K; k++){
      int l = k * sqrtN;
      int r = (k+1) * sqrtN;
      chmin(r,N);
      if(r <= s || t <= l) continue;
      if(s <= l && r <= t){
        x -= bucketAdd[k];
        y -= bucketAdd[k];
        int sz = r - l;
        // [0,y]
        int posY = upper_bound(sortedBucket[k].begin(),sortedBucket[k].end(),y) - sortedBucket[k].begin();
        // [0,x) 
        int posX = lower_bound(sortedBucket[k].begin(),sortedBucket[k].end(),x) - sortedBucket[k].begin();
        if(x <= bucketMax[k] && bucketMin[k] <= y){
          res += sz;
        }else if(x <= bucketMax[k] && bucketMax[k] <= y){
          res += posY;
        }else if(x <= bucketMin[k] && bucketMin[k] <= y){
          res += sz - posX;
        }else{
          res += posY - posX;
        }
        x += bucketAdd[k];
        y += bucketAdd[k];
      }else{
        eval(k);
        vector<ll> temp;
        for(int i=l; i<r; i++){
          temp.emplace_back(data[i]);
        }
        sort(temp.begin(),temp.end());
        sortedBucket[k] = temp;
        for(int i=max(l,s); i<min(r,t); i++){
          if(x <= data[i] && data[i] <= y) res++;
        }
      }
    }    
    return res;
  }
};

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int N,Q;
  cin >> N >> Q;
  vector<ll> A(N);
  for(int i=0; i<N; i++) cin >> A[i];
  SqrtDecomposition SD(A);
  vector<int> ans;
  for(int i=0; i<Q; i++){
    int id;
    cin >> id;
    if(id == 4){
      int l,r;
      ll x,y;
      cin >> l >> r >> x >> y;
      l--;
      ans.emplace_back(SD.query(l,r,x,y));
    }else{
      int l,r;
      ll x;
      cin >> l >> r >> x;
      l--;
      SD.update(id,l,r,x);
    }
  }
  for(auto x: ans){
    cout << x << eol;
  }
  return 0;
}
accuracy: 0.09523809523809523
time_ms: 120
memory_kb: 6200
final_rank: 17