线段树样例能过 10pts 求调,玄关。
查看原帖
线段树样例能过 10pts 求调,玄关。
941502
_Gabriel_楼主2023/9/3 11:36
#include <bits/stdc++.h> 
using namespace std;

typedef long long ll;
#define long long int
const int INF = 9e18;
const int N = 1e5 + 10;
int minv[N * 4], maxv[N * 4], sumv[N * 4], a[N], lazy[4 * N];
int n, m;

void pushup(int id) {
	minv[id] = min(minv[id << 1], minv[id << 1 | 1]);
	maxv[id] = max(maxv[id << 1], maxv[id << 1 | 1]);
	sumv[id] = sumv[id << 1] + sumv[id << 1 | 1];
}

void pushdown(int id, int l, int r) {
	if (lazy[id]) {
		int mid = (l + r) >> 1;
		//标记的下标
		lazy[id << 1] += lazy[id];
		lazy[id << 1 | 1] += lazy[id];
		//左区间更新
		minv[id << 1] += lazy[id];
		maxv[id << 1] += lazy[id];
		sumv[id << 1] += (mid - l + 1) * lazy[id];
		//右区间更新
		minv[id << 1 | 1] += lazy[id];
		maxv[id << 1 | 1] += lazy[id];
		sumv[id << 1 | 1] += (r - mid) * lazy[id];				
	}
}

//id 表示节点编号,l r 表示这个节点对应的区间 
void build(int id, int l, int r) {
    if (l == r) {
        //如果当前区间是长度为 1 的叶子节点 
        minv[id] = maxv[id] = sumv[id] = a[l];
        return;
    }
    //否则的话从中间拆分开左右两个区间 
    int mid = (l + r) >> 1;//(l + r) >> 1 ==> (l + r) / 2 
    build(id << 1, l, mid);//id << 1 ==> id * 2 
    build(id << 1 | 1, mid + 1, r);//id << 1 | 1 ==> id * 2 + 1 
    //左右两个孩子的结果全部计算完毕后
    //把结果合并到当前节点 
    pushup(id);
} 

void interval_update(int id, int l, int r, int x, int y, int v) {//区间更新
	if (x <= l && r <= y) {
		lazy[id] += v;
		minv[id] += v;
		maxv[id] += v;
		sumv[id] += (r - l + 1) * v;
		return;
 	}
 	pushdown(id, l, r);
 	int mid = (l + r) >> 1;
 	if (x <= mid) {
		interval_update(id << 1, l, mid, x, y, v);
	} 
	if (y > mid) {
		interval_update(id << 1 | 1, mid + 1, r, x, y, v);
	}
	pushup(id);
}

int query(int id, int l, int r, int x, int y) {
	if (x <= l && r <= y) {
		return sumv[id];
	}
	pushdown(id, l, r);
	int mid = (l + r) >> 1;
	int ans = 0;
	if (x <= mid) {
		ans += query(id << 1, l, mid, x, y);
	}  
	if (y > mid) {
		ans += query(id << 1 | 1, mid + 1, r, x, y);
	}
	return ans;
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
    build(1, 1, n);
	int op, x, y, k;
	for (int i = 1; i <= m; i++) {
		scanf("%d", &op);
		if (op == 1) {
			scanf("%d%d%d", &x, &y, &k);
			interval_update(1, 1, n, x, y, k);
		} else {
			scanf("%d%d", &x, &y);
			printf("%d\n", query(1, 1, n, x, y));
		}
	}
	return 0;
}
2023/9/3 11:36
加载中...