题目描述
如题,已知一个数列,你需要进行下面两种操作:
- 将某区间每一个数加上x
- 求出某区间每一个数的和
输入格式
第一行包含两个整数N、M,分别表示该数列数字的个数和操作的总个数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k
操作2: 格式:2 x y 含义:输出区间[x,y]内每个数的和
输出格式
输出包含若干行整数,即为所有操作2的结果。
输入输出样例
输入 #1复制
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
输出 #1复制
11
8
20
说明/提示
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000
(数据已经过加强_,保证在int64/long long数据范围内)
样例说明:
实现代码
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
ll a[maxn], ans;
struct node {
ll l, r, sum, add;
node() {}
node(int l, int r) : l(l), r(r), add(0) {}
}tree[maxn << 2];
inline ll lson(int id) { //线段树的左子树下标
return id << 1;
}
inline ll rson(int id) { //线段树的右子树下标
return id << 1 | 1;
}
inline ll len(int id) { //线段树的长度
return tree[id].r - tree[id].l + 1;
}
inline int Getmid(int id) { //线段树的中间数
return (tree[id].r + tree[id].l) >> 1;
}
void maintain(int id) { //维护
tree[id].sum = tree[lson(id)].sum + tree[rson(id)].sum;
}
void build(int id, int l, int r) { //建立线段树树
tree[id] = node(l, r);
if (l == r) {
tree[id].sum = a[l];
return;
}
int mid = (l + r) >> 1;
build(lson(id), l, mid);
build(rson(id), mid + 1, r);
maintain(id);
}
void pushdown(int id) { //懒人标记,向下传递
if (tree[id].add) {
ll tmp = tree[id].add;
tree[lson(id)].add += tmp;
tree[rson(id)].add += tmp;
tree[lson(id)].sum += tmp * len(lson(id));
tree[rson(id)].sum += tmp * len(rson(id));
tree[id].add = 0;
}
}
void update(int id, int l, int r, ll val) { //更新
if (tree[id].r < l || tree[id].l > r) return;
if (tree[id].r <= r && tree[id].l >= l) {
tree[id].add += val;
tree[id].sum += val * len(id);
return;
}
pushdown(id); //传递
update(lson(id), l, r, val); //更新左子树
update(rson(id), l, r, val); //更新右子树
maintain(id); //维护
}
void query(int id, int l, int r) { //查询操作
if (tree[id].r < l || tree[id].l > r) return;
if (tree[id].r <= r && tree[id].l >= l) {
ans += tree[id].sum;
return;
}
pushdown(id);
query(lson(id), l, r);
query(rson(id), l, r);
}
int main() {
int n, m, x, y;
ll k;
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while (m--) {
int ch;
cin >> ch;
if (ch == 1) {
cin >> x >> y >> k;
update(1, x, y, k);
}
if (ch == 2) {
ans = 0;
cin >> x >> y;
query(1, x, y);
cout << ans << endl;
}
}
return 0;
}