解题思路

整个题面一看就有着溢出屏幕的线段树的味道。那么任何使用线段树维护区间,我们使用线段树又要维护什么呢?
显然对于我们每次的修改,都是存在一定规律的,既公差的等差数列,并且每次求解的都是一段区间的和,那么我们就用标记推迟往下赋值的时间,并且使用记录区间的和,因为给出了首项,项数可以通过的距离求解,这样就可以通过求合公式求出来。每次把标记打上首项的值,这样在递归到下面层次的时候就可以直接求解到左右两边的对应权值。即可实现求解和更新答案。

#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
#define rep(i, sta, en) for(int i=sta; i<=en; ++i)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar())    s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op)    putchar(op); return; }    char F[40]; ll tmp = x > 0 ? x : -x;    if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]);    if (op)    putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1;    while (b) { if (b & 1)    ans *= a;        b >>= 1;        a *= a; }    return ans; }    ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 7;

#define mid ( l+r >> 1 )
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r

int a[N], n, m;
ll sum[N << 2], lazy[N << 2];

ll calc(ll a1, ll n) {
    return (a1 + a1 + n - 1) * n / 2;
}
void push_up(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; }
void push_down(int rt, int l, int r) {
    if (lazy[rt]) {
        lazy[rt << 1] = lazy[rt];
        lazy[rt << 1 | 1] = lazy[rt] + (mid - l + 1);
        sum[rt << 1] = calc(lazy[rt << 1], mid - l + 1); // [l,mid]
        sum[rt << 1 | 1] = calc(lazy[rt << 1 | 1], r - mid); // [mid+1,R]
        lazy[rt] = 0;
    }
}

void build(int rt, int l, int r) {
    if (l == r) {
        sum[rt] = a[l];
        return;
    }
    build(lson);
    build(rson);
    push_up(rt);
}

void update(int rt, int l, int r, int L, int R, int k) {
    if (L <= l and r <= R) {
        ll a1 = k + l - L, n = r - l + 1;
        lazy[rt] = a1;
        sum[rt] = calc(a1, n);
        return;
    }
    push_down(rt, l, r);
    if (L <= mid)    update(lson, L, R, k); // [L,mid]
    if (R > mid)    update(rson, L, R, k); // [mid+1,R]
    push_up(rt);
}

ll query(int rt, int l, int r, int L, int R) {
    if (L <= l and r <= R)    return sum[rt];
    push_down(rt, l, r);
    ll res = 0;
    if (L <= mid)    res += query(lson, L, R);
    if (R > mid)    res += query(rson, L, R);
    return res;
}

void solve() {
    n = read(), m = read();
    rep(i, 1, n)    a[i] = read();
    build(1, 1, n);
    while (m--) {
        int op = read(), l = read(), r = read();
        if (op & 1) {
            int k = read();
            update(1, 1, n, l, r, k);
        }
        else {
            ll ans = query(1, 1, n, l, r);
            print(ans);
        }
    }
}

int main() {
    //int T = read();    while (T--)
    solve();
    return 0;
}