作者:dishonest的你_507 | 来源:互联网 | 2024-11-16 11:49
线段树是一种高效的数据结构,常用于处理区间更新和查询问题。本文将详细介绍如何使用线段树实现区间加法和区间查询操作。
首先,我们需要包含一些必要的头文件,并定义一些基本的宏和变量:
#include
#include
#include
#include
#include
#include
#define LL long long
#define l(x) (x <<1)
#define r(x) ((x <<1) | 1)
using namespace std;
struct Tree {
LL sum, tag;
} Tr[500100];
LL a[500100];
接下来,我们定义一个更新函数,用于更新节点的值:
void update(LL id) {
Tr[id].sum = Tr[l(id)].sum + Tr[r(id)].sum;
}
然后,定义一个下推函数,用于将懒标记传递给子节点:
void pushdown(LL l, LL r, LL id) {
Tr[r(id)].tag += Tr[id].tag;
Tr[l(id)].tag += Tr[id].tag;
Tr[id].sum += (r - l + 1) * Tr[id].tag;
Tr[id].tag = 0;
}
接下来是构建线段树的函数:
void build(LL l, LL r, LL id) {
if (l == r) {
Tr[id].sum = a[l];
return;
}
LL mid = (l + r) / 2;
build(mid + 1, r, r(id));
build(l, mid, l(id));
update(id);
}
定义一个区间加法函数,用于在指定区间内增加一个值:
void add(LL al, LL ar, LL x, LL l, LL r, LL id) {
if (l > ar || r = al) add(al, min(mid, ar), x, l, mid, l(id));
if (mid
最后,定义一个区间查询函数,用于查询指定区间的和:
LL query(LL al, LL ar, LL l, LL r, LL id) {
if (l > r) return 0LL;
if (al == l && ar == r) {
return Tr[id].tag * (r - l + 1) + Tr[id].sum;
}
pushdown(l, r, id);
LL mid = (r + l) / 2;
LL t = 0;
if (mid >= al) t += query(al, min(mid, ar), l, mid, l(id));
if (mid
主函数部分,读取输入并进行相应的操作:
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
build(1, n, 1);
while (m--) {
int cas;
scanf("%d", &cas);
if (cas == 1) {
LL x, y, k;
scanf("%lld%lld%lld", &x, &y, &k);
add(x, y, k, 1, n, 1);
} else {
LL x, y;
scanf("%lld%lld", &x, &y);
printf("%lld\n", query(x, y, 1, n, 1));
}
}
return 0;
}
以上就是使用线段树实现区间加法和区间查询的完整代码。希望对大家有所帮助。