This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using i64 = long long;
constexpr i64 inf = 1ll << 60;
template <class M>
class segtree {
    int n, seg_size;
    using T = typename M::T;
    std::vector<T> tree;
    void update(int i) {
        tree[i] = M::operate(tree[2 * i], tree[2 * i + 1]);
    }
  public:
    segtree(int n_) : n(n_) {
        seg_size = 1;
        while (seg_size < n) {
            seg_size *= 2;
        }
        tree.assign(2 * seg_size, M::identity());
    }
    void set(int i, T v) {
        i += seg_size;
        tree[i] = v;
        while (i != 1) {
            i /= 2;
            update(i);
        }
    }
    T fold(int l, int r) {
        T ret_l = M::identity(), ret_r = M::identity();
        for (l += seg_size, r += seg_size; l < r; l /= 2, r /= 2) {
            if (l % 2 == 1) {
                ret_l = M::operate(ret_l, tree[l++]);
            }
            if (r % 2 == 1) {
                ret_r = M::operate(tree[--r], ret_r);
            }
        }
        return M::operate(ret_l, ret_r);
    }
    T get(int i) {
        return tree[i + seg_size];
    }
};
template <class M>
class lazy_segtree {
    int n, seg_size, logn;
    using T = typename M::T;
    using E = typename M::E;
    std::vector<T> tree;
    std::vector<E> lazy;
    void update(int i) {
        tree[i] = M::operate(tree[2 * i], tree[2 * i + 1]);
    }
    void apply(int i, const E &v) {
        tree[i] = M::map(tree[i], v);
        if (i < seg_size) {
            lazy[i] = M::composite(lazy[i], v);
        }
    }
    void flush(int i) {
        apply(2 * i, lazy[i]);
        apply(2 * i + 1, lazy[i]);
        lazy[i] = M::e_identity();
    }
  public:
    lazy_segtree(int n_) : n(n_) {
        logn = 1;
        while ((1 << logn) < n) {
            ++logn;
        }
        seg_size = 1 << logn;
        tree.assign(2 * seg_size, M::t_identity());
        lazy.assign(seg_size, M::e_identity());
    }
    void assign(int i, const T &v) {
        i += seg_size;
        for (int d = logn; d >= 1; --d) {
            flush(i >> d);
        }
        tree[i] = v;
        for (int d = 1; d <= logn; ++d) {
            update(i >> d);
        }
    }
    void operate_range(int l, int r, const E &v) {
        l += seg_size;
        r += seg_size;
        for (int d = logn; d >= 1; --d) {
            if (((l >> d) << d) != l) {
                flush(l >> d);
            }
            if (((r >> d) << d) != r) {
                flush((r - 1) >> d);
            }
        }
        for (int l2 = l, r2 = r; l2 < r2; l2 /= 2, r2 /= 2) {
            if (l2 % 2 == 1) {
                apply(l2++, v);
            }
            if (r2 % 2 == 1) {
                apply(--r2, v);
            }
        }
        for (int d = 1; d <= logn; ++d) {
            if (((l >> d) << d) != l) {
                update(l >> d);
            }
            if (((r >> d) << d) != r) {
                update((r - 1) >> d);
            }
        }
    }
    void operate_point(int i, const E &v) {
        operate_range(i, i + 1, v);
    }
    T fold(int l, int r) {
        l += seg_size;
        r += seg_size;
        for (int d = logn; d >= 1; --d) {
            if (((l >> d) << d) != l) {
                flush(l >> d);
            }
            if (((r >> d) << d) != r) {
                flush((r - 1) >> d);
            }
        }
        T ret_l = M::t_identity(), ret_r = M::t_identity();
        while (l < r) {
            if (l % 2 == 1) {
                ret_l = M::operate(ret_l, tree[l++]);
            }
            if (r % 2 == 1) {
                ret_r = M::operate(tree[--r], ret_r);
            }
            l /= 2;
            r /= 2;
        }
        return M::operate(ret_l, ret_r);
    }
};
struct M1 {
    // range sum
    struct T {
        i64 value;
        int width;
    };
    static T operate(T a, T b) {
        return {a.value + b.value, a.width + b.width};
    }
    static T t_identity() {
        return {0, 0};
    }
    struct E {
        i64 init;
        i64 add;
    };
    static T map(T a, E b) {
        if (b.init == inf) {
            return {a.value + a.width * b.add, a.width};
        } else {
            return {a.width * (b.init + b.add), a.width};
        }
    }
    static E composite(E a, E b) {
        if (b.init == inf) {
            return {a.init, a.add + b.add};
        } else {
            return b;
        }
    }
    static E e_identity() {
        return {inf, 0};
    }
};
struct M2 {
    // on off max
    struct T {
        int l;
        int r;
        int ma;
        int width;
    };
    static T operate(T l, T r) {
        if (l.width == -1) {
            return r;
        }
        if (r.width == -1) {
            return l;
        }
        T ret;
        ret.width = l.width + r.width;
        ret.l = l.l;
        ret.r = r.r;
        if (l.l == l.width) {
            ret.l = l.l + r.l;
        }
        if (r.r == r.width) {
            ret.r = l.r + r.r;
        }
        ret.ma = std::max({ret.l, ret.r, l.ma, r.ma, l.r + r.l});
        return ret;
    }
    static T identity() {
        return {0, 0, 0, -1};
    }
};
int main() {
    int N, Q;
    std::cin >> N >> Q;
    std::vector<i64> D(N);
    for (auto &e : D) {
        std::cin >> e;
    }
    std::vector<int> T(Q), L(Q), R(Q);
    std::vector<i64> S(Q), C(Q);
    for (int i = 0; i < Q; ++i) {
        std::cin >> T[i] >> L[i] >> R[i];
        --L[i];
        if (T[i] == 1 or T[i] == 2) {
            std::cin >> S[i] >> C[i];
        }
    }
    // diff of diff
    std::vector<i64> diffs(N - 1);
    for (int i = 1; i < N; ++i) {
        diffs[i - 1] = D[i] - D[i - 1];
    }
    diffs.insert(diffs.begin(), D[0]);
    lazy_segtree<M1> seg(N);
    for (int i = 0; i < N; ++i) {
        seg.assign(i, {diffs[i], 1});
    }
    auto access = [&](const int i) {
        return seg.fold(0, i + 1).value;
    };
    segtree<M2> oz(N - 2);
    std::set<int> zeros;
    for (int i = 2; i < N; ++i) {
        if (D[i] - D[i - 1] == D[i - 1] - D[i - 2]) {
            oz.set(i - 2, {1, 1, 1, 1});
        } else {
            oz.set(i - 2, {0, 0, 0, 1});
            zeros.insert(i - 2);
        }
    }
    auto update = [&](int i) {
        if (i >= N - 2 or i < 0) {
            return;
        }
        const auto a = access(i), b = access(i + 1), c = access(i + 2);
        if (b - a == c - b) {
            if (oz.get(i).ma == 1) {
                return;
            }
            oz.set(i, {1, 1, 1, 1});
            zeros.erase(i);
        } else {
            if (oz.get(i).ma == 0) {
                return;
            }
            oz.set(i, {0, 0, 0, 1});
            zeros.insert(i);
        }
    };
    auto range_set_one = [&](int l, int r) {
        // [l, r - 2)
        auto itr = zeros.lower_bound(l);
        while (itr != zeros.end()) {
            if (*itr >= r - 2) {
                break;
            }
            oz.set(*itr, {1, 1, 1, 1});
            itr = zeros.erase(itr);
        }  
    };
    for (int q = 0; q < Q; ++q) {
        if (T[q] == 1) {
            seg.operate_point(L[q], {inf, S[q]});
            seg.operate_range(L[q] + 1, R[q], {inf, C[q]});
            if (R[q] != N) {
                seg.operate_point(R[q], {inf, -(S[q] + (R[q] - L[q] - 1) * C[q])});
            }
            update(L[q] - 2);
            update(L[q] - 1);
            update(R[q] - 2);
            update(R[q] - 1);
        }
        if (T[q] == 2) {
            const auto lt = R[q] == N ? 0 : access(R[q]);
            const auto fa = access(L[q] - 1);
            seg.operate_point(L[q], {S[q] - fa, 0});
            seg.operate_range(L[q] + 1, R[q], {C[q], 0});
            if (R[q] != N) {
                seg.operate_point(R[q], {lt - (S[q] + (R[q] - L[q] - 1) * C[q]), 0});
            }
            update(L[q] - 2);
            update(L[q] - 1);
            update(R[q] - 2);
            update(R[q] - 1);
            range_set_one(L[q], R[q]);
        }
        if (T[q] == 3) {
            if (R[q] - L[q] <= 2) {
                std::cout << R[q] - L[q] << std::endl;
                continue;
            }
            const auto res = oz.fold(L[q], R[q] - 2).ma;
            std::cout << res + 2 << std::endl;
        }        
    }
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |