模板线段树(luogu P3372)
Posted zengpeichen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板线段树(luogu P3372)相关的知识,希望对你有一定的参考价值。
#include <cstdio> #define N 1000010 typedef long long ll; ll n, m, opt, p, q, s; ll a[N], add[N << 2], sum[N << 2]; void build(ll i, ll l, ll r){ //建树 if(l == r){ sum[i] = a[l]; return; }
ll mid = (l + r) >> 1; build(i << 1, l, mid); build(i << 1 | 1, mid + 1, r);
sum[i] = sum[i << 1] + sum[i << 1 | 1]; } void plu(ll i, ll l, ll r, ll v){ //加法运算 add[i] += v; sum[i] += (r - l + 1) * v; } void pushdown(ll i, ll l, ll r, ll mid){ //维护 Lazy-tag if(add[i] == 0) return;
plu(i << 1, l, mid, add[i]);
plu(i << 1 | 1, mid + 1, r, add[i]);
add[i] = 0; } ll query(ll i, ll l, ll r, ll x, ll y){ //询问区间和 if(l >= x && r <= y) return sum[i];
ll mid = (l + r) >> 1, ans = 0; pushdown(i, l, r, mid);
if(x <= mid) ans += query(i << 1, l, mid, x, y); if(y > mid) ans += query(i << 1 | 1, mid + 1, r, x, y);
return ans; } void modify(ll i, ll l, ll r, ll x, ll y, ll v){ //更新区间 if(l >= x && r <= y){ plu(i, l, r, v); return; }
ll mid = (l + r) >> 1; pushdown(i, l, r, mid);
if(x <= mid) modify(i << 1, l, mid, x, y, v); if(y > mid) modify(i << 1 | 1, mid + 1, r, x, y, v);
sum[i] = sum[i << 1] + sum[i << 1 | 1]; } int main(){
scanf("%lld%lld", &n, &m); for(ll i=1; i<=n; i++) scanf("%lld", &a[i]); build(1, 1, n);
while(m--){ scanf("%lld", &opt);
if(opt == 1){ scanf("%lld%lld%lld", &p, &q, &s); modify(1, 1, n, p, q, s); }
else{ scanf("%lld%lld", &p, &q); printf("%lld\n", query(1, 1, n, p, q)); } } return 0; }
以上是关于模板线段树(luogu P3372)的主要内容,如果未能解决你的问题,请参考以下文章