线段树模板自用c++

数据类型为long long(long long的最大值:9223372036854775807)

#include <iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 1000001
using namespace std;
unsigned long long  n;//总个数
unsigned long long tree [MAXN * 4];//线段树存储数组
unsigned long long tag [MAXN * 4];//lazy标签记录数组
unsigned long long a [MAXN];//存储读入数据
//根据序号x,寻找线段树的左右子树的序号
inline long long leftsearch(long long x) {
	return x * 2;
}
inline long long rightsearch(long long x) {
	return x * 2 + 1;
}
//构建线段树时,从最底层向上传递数据
inline void push_up(long long x) {
	tree[x] = tree[leftsearch(x)] + tree[rightsearch(x)];
}
//创建线段树
void build(long long x, long long left, long long right) {
	tag[x] = 0;
	if (left == right) {//终止条件
		tree[x] = a[left];
		return;
	}
	long long mid = (left + right) / 2;
	build(leftsearch(x), left, mid);//创建左子树
	build(rightsearch(x), mid + 1, right);//创建右子树
	push_up(x);//向上更新数据
}
//区间修改
inline void f(long long x, long long left, long long right, long long k) {//区间加法
	tag[x] = tag[x] + k;
	tree[x] = tree[x] + k * (right - left + 1);
}
inline void push_down(long long x, long long left, long long right) {
	long long mid = (left + right) / 2;
	f(leftsearch(x), left, mid, tag[x]);
	f(rightsearch(x), mid + 1, right, tag[x]);
	tag[x] = 0;
}
inline void update(long long nleft, long long nright, long long left, long long right, long long x, long long k) {//区间加法
	if (nleft <= left && nright >= right) {
		tree[x] += k * (right - left + 1);
		tag[x] += k;
		return ;
	}
	push_down(x, left, right);
	long long mid = (left + right) / 2;
	if (nleft <= mid)update(nleft, nright, left, mid, leftsearch(x), k);
	if (nright > mid)update(nleft, nright, mid + 1, right, rightsearch(x), k);
	push_up(x);
}
//区间查询
long long query(long long nleft, long long nright, long long left, long long right, long long x) {
	long long res = 0;
	if (nleft <= left && nright >= right)return tree[x];
	long long mid = (left + right) / 2;
	push_down(x, left, right);
	if (nleft <= mid)res += query(nleft, nright, left, mid, leftsearch(x));
	if (nright > mid)res += query(nleft, nright, mid + 1, right, rightsearch(x));
	return res;
}

以上为线段树基本函数;

配合洛谷p3372题,写出主函数:

int main()
{
	cin >> n >> m;
	long long  x,b,c,d,e,f;
	
	for (long long  i = 1; i <= n; i++) {
		scanf_s("%lld", &a[i]);
	}
	build(1, 1, n);
	for (long long  i = 0; i < m; i++) {
		int key;
		scanf_s("%d", &key);
		switch (key)
		{
		case 1: {
			scanf_s("%lld%lld%lld", &b, &c, &d);
			update(b, c, 1, n, 1, d);
			break;
		}
		case 2: {
			scanf_s("%lld%lld", &e, &f);
			printf("%lld\n", query(e, f, 1, n, 1));
			break;
		}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值