线段树模板

以下为为求区间和,求区间最大值,最小值模板

题目以 敌兵布阵

HDU - 1166   为例子

 #include <iostream>
 #include <algorithm>
 #include <string.h>
 #include <cstdio>
 #include <string>
 #include <cmath>
 #include <vector>
 #include <stack>
 #include <queue>
 #include <stack>
 #include <list>
 #include <map>
 #include <set>
 //#include <unordered_map>
 #define Fbo friend bool operator < (node a, node b)
 #define mem(a, b) memset(a, b, sizeof(a))
 #define FOR(a, b, c) for (int a = b; a <= c; a++)
 #define RFOR(a, b, c) for (int a = b; a >= c; a--)
 #define off ios::sync_with_stdio(0)
 bool check1(int a) { return (a & (a - 1)) == 0 ? true : false; }

 using namespace std;
 typedef pair<int, int> pii;
 typedef long long ll;
 const int INF = 0x3f3f3f3f;
 const int mod = 1e9 + 7;
 const int Maxn = 2e5 + 5;
 const double pi = acos(-1.0);
 const double eps = 1e-8;

 ll a[Maxn];

 struct node {
         ll l, r;//区间[l,r]
         ll add;//区间的延时标记
         ll sum;//区间和
         int maxn; //区间最大值
         int 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].add += tree[rt].add;
        tree[rt << 1 | 1].add += 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].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].add = 0;  //取消本层标记


    }

}
void BuildTree(ll l, ll r, ll rt) {
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].add = 0;//刚开始一定要清0
    tree[rt].sum = r - l + 1; //更新结点rt的值
    if (l == r) {
        //此行根据题意看情况填什么————-
        tree[rt].sum = a[l];
        //————————————————
        return;

    }
    ll mid = (l + r) >> 1;
    BuildTree(l, mid, rt << 1); //递归左子树
    BuildTree(mid + 1, r, (rt << 1) + 1); //递归右子树
    pushup(rt);//向上更新

}
void updata(ll l, ll r, ll val, ll rt) { //root为结点 区间更新
       // cout << l << " " << tree[rt].l << "----" << r << " " << tree[rt].r << endl;  验证路径
    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].minn = val
        tree[rt].maxn += 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, val, rt << 1);

    }
    if (r > mid) {
        updata(l, r, val, rt << 1 | 1);

    }
    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 t, n, x, y;
    scanf("%lld", &t);
    FOR(i, 1, t) {
        string s;
        scanf("%lld", &n);
        printf("Case %d:\n", i);
        FOR(j, 1, n)scanf("%d", &a[j]);
        BuildTree(1, n, 1);
        while (1) {
            cin >> s;
            if (s == "End") break;
            scanf("%lld%lld", &x, &y);
            if (s == "Query") cout << querySum(x, y, 1) << endl;
            if (s == "Add") updata(x, x, y, 1);//[a,a]的元素更新为b
            if (s == "Sub") updata(x, x, -y, 1);

        }

    }
    return 0;
}

 

posted @ 2020-04-04 22:13  AlexLIN·  阅读(143)  评论(0)    收藏  举报