这是算区间和的线段树的模板
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define ll long long
#define fori for(i=0;i<n;i++)
#define fori1 for(i=1;i<=n;i++)
using namespace std;
const int maxn = 1e6 + 107;
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
struct node {
ll l, r;//区间[l,r]
ll add;//区间的延时标记
ll sum;//区间和
ll maxn; //区间最大值
ll minn; //区间最小值
}tree[maxn * 4 + 5];//一定要开到4倍多的空间
void pushup(ll rt) {
tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
tree[rt].maxn = max(tree[rt << 1].maxn, tree[rt << 1 | 1].maxn);
tree[rt].minn = min(tree[rt << 1].minn, tree[rt << 1 | 1].minn);
}
void pushdown(ll rt) {
if (tree[rt].add) {
tree[rt << 1].sum += (tree[rt << 1].r - tree[rt << 1].l + 1) * tree[rt].add;
tree[rt << 1 | 1].sum += (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1) * tree[rt].add;
tree[rt << 1].maxn += tree[rt].add;
tree[rt << 1 | 1].maxn += tree[rt].add;
tree[rt << 1].minn += tree[rt].add;
tree[rt << 1 | 1].minn += tree[rt].add;
tree[rt << 1].add += tree[rt].add;
tree[rt << 1 | 1].add += tree[rt].add;
tree[rt].add = 0;
}
}
void build(ll l, ll r, ll rt) {
tree[rt].l = l;
tree[rt].r = r;
tree[rt].add = 0;//刚开始一定要清0
if (l == r) {
cin>>tree[rt].sum;
tree[rt].minn = tree[rt].maxn = tree[rt].sum;
return;
}
ll mid = (l + r) >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
pushup(rt);
}
void updata(ll l, ll r, ll rt, ll val) {
if (l <= tree[rt].l && r >= tree[rt].r) {
tree[rt].sum += (tree[rt].r - tree[rt].l + 1) * val;
tree[rt].minn += val;
tree[rt].maxn += val;
tree[rt].add += val;//延时标记
return;
}
pushdown(rt);
ll mid = (tree[rt].l + tree[rt].r) >> 1;
if (l <= mid) {
updata(l, r, rt << 1, val);
}
if (r > mid) {
updata(l, r, rt << 1 | 1, val);
}
pushup(rt);
}
ll querySum(ll l, ll r, ll rt) {
if (l <= tree[rt].l && r >= tree[rt].r) {
return tree[rt].sum;
}
pushdown(rt);
ll mid = (tree[rt].l + tree[rt].r) >> 1;
ll ans = 0;
ll Max = 0;
ll Min = inf;
if (l <= mid) {
ans += querySum(l, r, rt << 1);
}
if (r > mid) {
ans += querySum(l, r, rt << 1 | 1);
}
return ans;
}
ll queryMin(ll l, ll r, ll rt) {
if (l <= tree[rt].l && r >= tree[rt].r) {
return tree[rt].minn;
}
pushdown(rt);
ll mid = (tree[rt].l + tree[rt].r) >> 1;
ll ans = 0;
ll Max = 0;
ll Min = inf;
if (l <= mid) {
Min = min(queryMin(l, r, rt << 1), Min);
}
if (r > mid) {
Min = min(queryMin(l, r, rt << 1 | 1), Min);
}
return Min;
}
ll queryMax(ll l, ll r, ll rt) {
if (l <= tree[rt].l && r >= tree[rt].r) {
return tree[rt].maxn;
}
pushdown(rt);
ll mid = (tree[rt].l + tree[rt].r) >> 1;
ll ans = 0;
ll Max = 0;
ll Min = inf;
if (l <= mid) {
Max = max(queryMax(l, r, rt << 1), Max);
}
if (r > mid) {
Max = max(queryMax(l, r, rt << 1 | 1), Max);
}
return Max;
}
int main()
{
ll i, j, k;
ll n, m;
ll x, y;
cin >> n >> m;
build(1, n, 1);
while (m--)
{
ll g;
cin >> g;
if (g == 1)
{
cin >> x >> y >> k;
updata(x, y, 1, k);
}
if (g == 2)
{
cin >> x >> y;
cout << querySum(x, y, 1) << endl;
}
}
}