模板线段树
Posted xuyixuan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板线段树相关的知识,希望对你有一定的参考价值。
题意简述
已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.求出某区间每一个数的和
代码
#include <cstdio>
using namespace std;
typedef long long ll;
ll n, m, opt, x, y, k;
ll a[400010], la[400010];
void push_up(ll x)
{
a[x] = a[x << 1] + a[x << 1 | 1];
}
void push_down(ll x, ll len)
{
a[x << 1] += la[x] * (len - (len >> 1));
a[x << 1 | 1] += la[x] * (len >> 1);
la[x << 1] += la[x];
la[x << 1 | 1] += la[x];
la[x] = 0;
}
void build(ll x, ll l, ll r)
{
if (l == r)
{
scanf("%d", &a[x]);
return;
}
ll mid = l + r >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
push_up(x);
}
void add(ll x, ll l, ll r, ll l1, ll r1)
{
if (l1 <= l && r <= r1)
{
a[x] += (r - l + 1) * k;
la[x] += k;
return;
}
if (la[x]) push_down(x, r - l + 1);
ll mid = l + r >> 1;
if (l1 <= mid) add(x << 1, l, mid, l1, r1);
if (r1 > mid) add(x << 1 | 1, mid + 1, r, l1, r1);
push_up(x);
}
ll query(ll x, ll l, ll r, ll l1, ll r1, ll ans = 0)
{
if (l1 <= l && r <= r1) return a[x];
if (la[x]) push_down(x, r - l + 1);
ll mid = l + r >> 1;
if (l1 <= mid) ans += query(x << 1, l, mid, l1, r1);
if (r1 > mid) ans += query(x << 1 | 1, mid + 1, r, l1, r1);
return ans;
}
int main()
{
scanf("%lld%lld", &n, &m);
build(1, 1, n);
for (register ll i = 1; i <= m; ++i)
{
scanf("%lld", &opt);
if (opt == 1)
{
scanf("%lld%lld%lld", &x, &y, &k);
add(1, 1, n, x, y);
}
else
{
scanf("%lld%lld", &x, &y);
printf("%lld
", query(1, 1, n, x, y));
}
}
}
以上是关于模板线段树的主要内容,如果未能解决你的问题,请参考以下文章