August8321 @ 2024-03-21 19:47:07
#include <bits/stdc++.h>
#define ll long long
#define MAXN 1000005
using namespace std;
ll n, m, opt, x, y, k,a[MAXN];
struct node
{
ll key, l, r, lazy = 0;
} t[MAXN];
void push_up(ll i) // 更新节点i的key
{
t[i].key = t[i << 1].key + t[i << 1 | 1].key;
}
void push_down(ll l, ll r, ll i)
{
ll mid = (l + r) >> 1;
t[i << 1].lazy += t[i].lazy; // 更新左子树lazy值
t[i << 1 | 1].lazy += t[i].lazy; // 更新右子树lazy值
t[i << 1].key += t[i].lazy * (mid - l + 1);
t[i << 1 | 1].key += t[i].lazy * (r - mid);
t[i].lazy = 0;
}
void Build(ll l, ll r, ll i)//建树
{
t[i].l = l;
t[i].r = r;
if (l == r)
{
t[i].key = a[l];
return;
}
ll mid = (l + r) >> 1;
Build(l, mid, i << 1);
Build(mid + 1, r, i << 1 | 1);
push_up(i);
}
ll Sum(ll l, ll r, ll i)//查询区间和
{
if (l <= t[i].l && t[i].r <= r)
{
return t[i].key;
}
push_down(l, r, i);
ll s = 0, mid = (t[i].l + t[i].r) >> 1;
if (l <= mid)
{
s += Sum(l, r, i << 1);
}
if (mid < r)
{
s += Sum(l, r, i << 1 | 1);
}
return s;
}
void update(ll l, ll r, ll i, ll k)
// 当前到了编号为i的节点,要把[l..r]区间中的所有元素的值+k
{
if (l <= t[i].l && t[i].r <= r) // 如果当前节点的区间真包含于要更新的区间内
{
t[i].key += (t[i].r - t[i].l + 1) * k; // 更新该区间的sum
t[i].lazy += k; // 懒惰标记叠加
return;
}
push_down(t[i].l, t[i].r, i); // 查询lazy标记,更新子树
ll mid = (t[i].l + t[i].r) >> 1;
if (l <= mid)
{
update(l, r, i << 1, k);
} // 如果左子树与需要更新的区间有交集
if (mid < r)
{
update(l, r, i << 1 | 1, k);
} // 如果右子树与需要更新的区间有交集
push_up(i); // 更新父节点
}
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
Build(1, n, 1);
for (int i = 1; i <= m; i++)
{
cin >> opt;
if (opt == 1)
{
cin >> x >> y >> k;
update(x, y, 1, k);
}
else
{
cin >> x >> y;
cout << Sum(x, y, 1) << endl;
}
}
return 0;
}