线段树区间和模板

 

这是算区间和的线段树的模板

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#define ll long long
#define fori for(i=0;i<n;i++)
#define fori1 for(i=1;i<=n;i++)
using namespace std;
const int maxn = 1e6 + 107;
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;


struct node {
    ll l, r;//区间[l,r]
    ll add;//区间的延时标记
    ll sum;//区间和
    ll maxn; //区间最大值
    ll minn; //区间最小值
}tree[maxn * 4 + 5];//一定要开到4倍多的空间

void pushup(ll rt) {
    tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
    tree[rt].maxn = max(tree[rt << 1].maxn, tree[rt << 1 | 1].maxn);
    tree[rt].minn = min(tree[rt << 1].minn, tree[rt << 1 | 1].minn);
}
void pushdown(ll rt) {
    if (tree[rt].add) {

        tree[rt << 1].sum += (tree[rt << 1].r - tree[rt << 1].l + 1) * tree[rt].add;
        tree[rt << 1 | 1].sum += (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1) * tree[rt].add;
        tree[rt << 1].maxn += tree[rt].add;
        tree[rt << 1 | 1].maxn += tree[rt].add;
        tree[rt << 1].minn += tree[rt].add;
        tree[rt << 1 | 1].minn += tree[rt].add;
        tree[rt << 1].add += tree[rt].add;
        tree[rt << 1 | 1].add += tree[rt].add;
        tree[rt].add = 0;

    }
}
void build(ll l, ll r, ll rt) {
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].add = 0;//刚开始一定要清0
    if (l == r) {
        cin>>tree[rt].sum;
        tree[rt].minn = tree[rt].maxn = tree[rt].sum;
        return;
    }
    ll mid = (l + r) >> 1;
    build(l, mid, rt << 1);
    build(mid + 1, r, rt << 1 | 1);
    pushup(rt);
}
void updata(ll l, ll r, ll rt, ll val) {
    if (l <= tree[rt].l && r >= tree[rt].r) {
        tree[rt].sum += (tree[rt].r - tree[rt].l + 1) * val;
        tree[rt].minn += val;
        tree[rt].maxn += val;
        tree[rt].add += val;//延时标记

        return;
    }
    pushdown(rt);
    ll mid = (tree[rt].l + tree[rt].r) >> 1;
    if (l <= mid) {
        updata(l, r, rt << 1, val);
    }
    if (r > mid) {
        updata(l, r, rt << 1 | 1, val);
    }
    pushup(rt);
}
ll querySum(ll l, ll r, ll rt) {
    if (l <= tree[rt].l && r >= tree[rt].r) {
        return tree[rt].sum;
    }
    pushdown(rt);
    ll mid = (tree[rt].l + tree[rt].r) >> 1;
    ll ans = 0;
    ll Max = 0;
    ll Min = inf;
    if (l <= mid) {
        ans += querySum(l, r, rt << 1);
    }
    if (r > mid) {
        ans += querySum(l, r, rt << 1 | 1);
    }
    return ans;
}
ll queryMin(ll l, ll r, ll rt) {
    if (l <= tree[rt].l && r >= tree[rt].r) {
        return tree[rt].minn;
    }
    pushdown(rt);
    ll mid = (tree[rt].l + tree[rt].r) >> 1;
    ll ans = 0;
    ll Max = 0;
    ll Min = inf;
    if (l <= mid) {
        Min = min(queryMin(l, r, rt << 1), Min);
    }
    if (r > mid) {
        Min = min(queryMin(l, r, rt << 1 | 1), Min);
    }
    return Min;
}
ll queryMax(ll l, ll r, ll rt) {
    if (l <= tree[rt].l && r >= tree[rt].r) {
        return tree[rt].maxn;
    }
    pushdown(rt);
    ll mid = (tree[rt].l + tree[rt].r) >> 1;
    ll ans = 0;
    ll Max = 0;
    ll Min = inf;
    if (l <= mid) {
        Max = max(queryMax(l, r, rt << 1), Max);
    }
    if (r > mid) {
        Max = max(queryMax(l, r, rt << 1 | 1), Max);
    }
 
    return Max;
}
int main()
{
    ll i, j, k;
    ll n, m;
    ll x, y;
    cin >> n >> m;
    build(1, n, 1);
    while (m--)
    {
        ll g;
        cin >> g;
        if (g == 1)
        {
            cin >> x >> y >> k;
            updata(x, y, 1, k);
        }
        if (g == 2)
        {
            cin >> x >> y;
            cout << querySum(x, y, 1) << endl;
        }
    }
}

 

posted @ 2020-04-02 14:30  ch_hui  阅读(156)  评论(0编辑  收藏  举报