#include <bits/stdc++.h>
#pragma GCC optimize("O3")

using namespace std;
typedef long long ll;

struct Node {
    ll sum, max_pref, min_pref, max_suff, min_suff, max_sub, min_sub;
    bool is_null;
    
    Node() : is_null(true) {}
    
    Node(ll val) {
        sum = max_pref = min_pref = max_suff = min_suff = max_sub = min_sub = val;
        is_null = false;
    }
};

class SegmentTree {
private:
    int n;
    vector<Node> tree;
    vector<ll> lazy_val;
    vector<bool> has_lazy;

    Node merge(const Node& L, const Node& R) {
        if (L.is_null) return R;
        if (R.is_null) return L;
        
        Node res;
        res.is_null = false;
        res.sum = L.sum + R.sum;
        res.max_pref = max(L.max_pref, L.sum + R.max_pref);
        res.min_pref = min(L.min_pref, L.sum + R.min_pref);
        res.max_suff = max(R.max_suff, R.sum + L.max_suff);
        res.min_suff = min(R.min_suff, R.sum + L.min_suff);
        res.max_sub = max({L.max_sub, R.max_sub, L.max_suff + R.max_pref});
        res.min_sub = min({L.min_sub, R.min_sub, L.min_suff + R.min_pref});
        return res;
    }

    void apply_lazy(int node, int L, int R, ll val) {
        int len = R - L + 1;
        ll start_sign = (L % 2 == 1) ? 1 : -1;
        ll end_sign = (R % 2 == 1) ? 1 : -1;
        
        ll first_val = start_sign * val;
        ll last_val = end_sign * val;
        
        if (len == 1) {
            tree[node] = Node(first_val);
        } else {
            tree[node].is_null = false;
            tree[node].sum = (len % 2 != 0) ? first_val : 0;
            tree[node].max_pref = max(0LL, first_val);
            tree[node].min_pref = min(0LL, first_val);
            tree[node].max_suff = max(0LL, last_val);
            tree[node].min_suff = min(0LL, last_val);
            tree[node].max_sub = abs(val);
            tree[node].min_sub = -abs(val);
        }
        
        lazy_val[node] = val;
        has_lazy[node] = true;
    }

    void push(int node, int L, int R) {
        if (has_lazy[node]) {
            int mid = (L + R) / 2;
            ll val = lazy_val[node];
            
            apply_lazy(node << 1, L, mid, val);
            apply_lazy(node << 1 | 1, mid + 1, R, val);
            
            has_lazy[node] = false;
        }
    }

    void build(int node, int L, int R, const vector<int>& v) {
        if (L == R) {
            ll signed_val = (L % 2 == 1) ? v[L] : -v[L];
            tree[node] = Node(signed_val);
            return;
        }
        
        int mid = (L + R) / 2;
        build(node << 1, L, mid, v);
        build(node << 1 | 1, mid + 1, R, v);
        
        tree[node] = merge(tree[node << 1], tree[node << 1 | 1]);
    }

    void update_range(int node, int L, int R, int Lq, int Rq, ll val) {
        if (R < Lq || L > Rq) return;
        
        if (Lq <= L && R <= Rq) {
            apply_lazy(node, L, R, val);
            return;
        }
        
        push(node, L, R);
        int mid = (L + R) / 2;
        
        update_range(node << 1, L, mid, Lq, Rq, val);
        update_range(node << 1 | 1, mid + 1, R, Lq, Rq, val);
            
        tree[node] = merge(tree[node << 1], tree[node << 1 | 1]);
    }

    Node query(int node, int L, int R, int Lq, int Rq) {
        if (R < Lq || L > Rq) return Node(); 
        if (Lq <= L && R <= Rq) return tree[node];
        
        push(node, L, R);
        int mid = (L + R) / 2;
        
        return merge(query(node << 1, L, mid, Lq, Rq), 
                     query(node << 1 | 1, mid + 1, R, Lq, Rq));
    }

public:
    SegmentTree(int size, const vector<int>& v) {
        n = size;
        tree.resize(4 * n + 1);
        lazy_val.resize(4 * n + 1, 0);
        has_lazy.resize(4 * n + 1, false);
        build(1, 1, n, v);
    }

    void update(int L, int R, ll val) {
        update_range(1, 1, n, L, R, val);
    }

    ll query_max_alternating(int L, int R) {
        Node res = query(1, 1, n, L, R);
        if (res.is_null) return 0;
        return max(res.max_sub, -res.min_sub);
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    
    int n, q;
    if (!(cin >> n >> q)) return 0;
    
    vector<int> v(n + 1);
    for(int i = 1; i <= n; i++) cin >> v[i];
    
    SegmentTree st(n, v);
    
    for(int i = 1; i <= q; i++) {
        int tip, a, b;
        cin >> tip >> a >> b;
        
        if (tip == 1) {
            st.update(a, a, b); 
        } 
        else if (tip == 2) {
            ll val;
            cin >> val;
            st.update(a, b, val);
        } 
        else if (tip == 3) {
            cout << st.query_max_alternating(a, b) << '\n';
        }
    }
    
    return 0;
}
