/*#include<iostream>
#include<string>
#include<vector>
#include<array>
#include<queue>
#include<stack>
#include<algorithm>*/
#include<bits/stdc++.h>
using namespace std;

#define all(x) x.begin(), x.end()

using i64 = long long;
using f64 = double;
using vi = vector<i64>;

constexpr char nl = '\n';
constexpr i64 N = 1e5;
constexpr f64 err = 1e-6;
constexpr int INF = 2e9;

struct Lazy
{
    struct Node
    {
        i64 sum = 0;
        int replace = INF;
        i64 add = 0;
    };
    
    int n;
    vector<Node> tree;
    
    Lazy(vector<int> const& v)
    {
        n = v.size();
        tree.resize(4*n);
        build(1, 0, n, v);
    }
    
    Node Op(Node const& x, Node const& y)
    {
        return {x.sum + y.sum, INF, 0};
    }
    
    #define LC i << 1
    #define RC i << 1 | 1
    #define MD (l + r) / 2
    
    void build(int i, int l, int r, vector<int> const& v)
    {
        if(l+1 == r)
        {
            tree[i].sum = v[l];
            return;
        }
        
        build(LC, l, MD, v);
        build(RC, MD, r, v);
        tree[i] = Op(tree[LC], tree[RC]);
    }
    
    void push(int i, int l, int r)
    {
        if(tree[i].replace != INF)
        {
            tree[LC].sum = 1LL * tree[i].replace * (MD - l);
            tree[RC].sum = 1LL * tree[i].replace * (r - MD);
            
            tree[LC].replace = tree[RC].replace = tree[i].replace;
            tree[LC].add = tree[RC].add = 0;
            
            tree[i].replace = INF;
        }
        
        tree[LC].sum += tree[i].add * (MD - l);
        tree[RC].sum += tree[i].add * (r - MD);
        
        tree[LC].add += tree[i].add;
        tree[RC].add += tree[i].add;
        
        tree[i].add = 0;
    }
    
    void upd(int i, int l, int r, int lo, int hi, int v, bool fl)
    {
        if(l == lo && r == hi)
        {
            if(fl)
            {
                tree[i].sum += 1LL * v * (r - l);
                tree[i].add += v;
            }
            else
            {
                tree[i].sum = 1LL *     v * (r - l);
                tree[i].replace = v;
                tree[i].add = 0;
            }
            
            return;
        }
        
        push(i, l, r);
        
        if(hi <= MD)
            upd(LC, l,  MD, lo, hi, v, fl);
        else if(MD <= lo)
            upd(RC, MD, r, lo, hi, v, fl);
        else
        {
            upd(LC, l, MD, lo, MD, v, fl);
            upd(RC, MD, r, MD, hi, v, fl);
        }
        
        tree[i] = Op(tree[LC], tree[RC]);
    }
    
    Node ask(int i, int l, int r, int lo, int hi)
    {
        if(l == lo && r == hi)
            return tree[i];
            
        push(i, l, r);
        
        if(hi <= MD)
            return ask(LC, l, MD, lo, hi);
        else if(MD <= lo)
            return ask(RC, MD, r, lo, hi);
        return Op(ask(LC, l, MD, lo, MD), ask(RC, MD, r, MD, hi));
    }
    
    #undef LC
    #undef RC
    #undef MD
    
    void upd(int l, int r, int v, bool fl)
    {
        upd(1, 0, n, l, r, v, fl);
    }
    
    i64 ask(int l, int r)
    {
        return ask(1, 0, n, l, r).sum;
    }
};

void solve()
{
    int n, q;
    cin >> n >> q;
    
    vector<int> v(n);
    for(auto&& i : v)
        cin >> i;
        
    Lazy tree(v);
    
    while(q--)
    {
        int t, l, r, x;
        cin >> t >> l >> r;
        --l, --r;
        
        if(t == 1)
        {
            cin >> x;
            tree.upd(l, r+1, x, true);
        }
        else if(t == 2)
        {
            cin >> x;
            tree.upd(l, r+1, x, false);
        }
        else
            cout << tree.ask(l, r+1) << nl;
    }    
}

int main()
{
    ios_base::sync_with_stdio(false), cin.tie(nullptr);
    
    int t = 1;
    // cin >> t;
    for(int i = 1; i <= t; ++i)
    {
        solve();
    }
}