呜呜呜一道模板题在懒节点上找错找了快一个小时我是飞舞。
洛谷传送门
题目
如题,已知一个数列,你需要进行下面两种操作:
将某区间每一个数加上 kkk。
求出某区间每一个数的和。
输入格式
第一行包含两个整数 n,mn, mn,m,分别表示该数列数字的个数和操作的总个数。
第二行包含 nnn 个用空格分隔的整数,其中第 iii 个数字表示数列第 iii 项的初始值。
接下来 mmm 行每行包含 333 或 444 个整数,表示一个操作,具体如下:
1 x y k:将区间 [x,y][x, y][x,y] 内每个数加上 kkk。
2 x y:输出区间 [x,y][x, y][x,y] 内每个数的和。
输出格式
输出包含若干行整数,即为所有操作 2 的结果。
Input
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
Output
11
8
20
解题思路
主要是对懒节点的处理一定要娴熟。
代码实现了模块化。
用了结构体记录树。
看起来应该会好看一些。
代码
#include<bits/stdc++.h>
using namespace std;
#define lson left, mid, rt<<1
#define rson mid+1, right, rt<<1|1
#define ls rt<<1 //相当于rt*2
#define rs rt<<1|1 //相当于rt*2+1
#define MAXN 1000010
#define IOS ios::sync_with_stdio(false);
#define FRE freopen("1.txt", "r", stdin)
#define ll long long int
int re[MAXN]; //记录要初始化的值
struct Tree {
int left, right;
ll val, lazy;
}tree[MAXN << 2]; //相当于MAXN*4
void push_up(int rt){
if(tree[rt].left == tree[rt].right) return;
tree[rt].val = tree[ls].val + tree[rs].val;
}
void buildTree(int left, int right, int rt) {
if(left == right){
tree[rt].left = tree[rt].right = left;
tree[rt].val = re[left];
tree[rt].lazy = 0;
return;
}
tree[rt].left = left;
tree[rt].right = right;
tree[rt].lazy = 0;
int mid = left + right >> 1; //相当于(left + right) / 2,优先级比较低
buildTree(lson);
buildTree(rson);
push_up(rt);
}
void down(int rt) {
if(tree[rt].left == tree[rt].right){
tree[rt].lazy = 0;
return;
}
tree[rs].lazy += tree[rt].lazy; //想一下为什么是 += 而不是 =
tree[ls].lazy += tree[rt].lazy;
tree[rs].val += (tree[rs].right - tree[rs].left + 1) * tree[rt].lazy;
tree[ls].val += (tree[ls].right - tree[ls].left + 1) * tree[rt].lazy;
tree[rt].lazy = 0;
}
void update(int left, int right, int rt, int add) {
if(tree[rt].left == left && tree[rt].right == right){
tree[rt].lazy += add;
tree[rt].val += (tree[rt].right - tree[rt].left + 1) * add;
return;
}
if(tree[rt].lazy) down(rt);
int mid = tree[rt].left + tree[rt].right >> 1;
if(left <= mid && right <= mid) update(left, right, ls, add);
else if(left > mid) update(left, right, rs, add);
else { update(lson, add); update(rson, add); }
push_up(rt);
}
ll query(int left, int right, int rt){
if(tree[rt].left == left && tree[rt].right == right){
if(tree[rt].lazy) down(rt);
return tree[rt].val;
}
if(tree[rt].lazy) down(rt);
int mid = tree[rt].left + tree[rt].right >> 1;
ll ans = 0;
if(left <= mid && right <= mid) ans = query(left, right, ls);
else if(left > mid) ans = query(left, right, rs);
else { ans += query(lson); ans += query(rson); }
return ans;
}
int main(int argc, char** argv) {
IOS; //加速
int n, m; cin >> n >> m;
for(int i = 1; i <= n; i++){
cin >> re[i];
}
buildTree(1, n, 1); //建树
while(m--){
int t; cin >> t;
if(t == 1){
int x, y, add; cin >> x >> y >> add;
if(x > y) swap(x, y);
update(x, y, 1, add); //更新维护
}else{
int x, y; cin >> x >> y;
if(x > y) swap(x, y);
cout << query(x, y, 1) << endl; //查区间值
}
}
return 0;
}