线段树模板(poj3468)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<sstream>
#include<string>
#include<bitset>
using namespace std;


typedef long long LL;


const LL LINF = (1LL <<63);
const int INF = 1 << 31;




const int NS = 500010;
const int MS = 19;
const int MOD = 1000000007;


typedef LL Ntype;
const int TSIZE = 500010;


struct tNode{
    int ls, rs;             //左右儿子的节点ID
    int lid, rid, len;      //节点的左右边界及长度
    Ntype minv, maxv;       //记录子树节点的价值最值
    Ntype sumv;             //记录子树节点的价值和
    Ntype addv;             //记录子树节点的增量


    bool isLeaf()
    {
        return (lid == rid);
    }
};


struct lineTree{
    #define lson(x) (x << 1)
    #define rson(x) ((x << 1) + 1)
    #define pmid(l, r) ((l + r) >> 1)


    int maxrt;
    tNode wt[TSIZE << 2];
    Ntype val[TSIZE];




    Ntype cmax(Ntype va, Ntype vb)
    {
        return (va > vb? va : vb);
    }


    Ntype cmin(Ntype va, Ntype vb)
    {
        return (va < vb? va : vb);
    }


    void PushUpUpdate(int rt)
    {
        int ls = wt[rt].ls;
        int rs = wt[rt].rs;


        wt[rt].maxv = cmax(wt[ls].maxv, wt[rs].maxv);
        wt[rt].minv = cmin(wt[ls].minv, wt[rs].minv);


        wt[rt].sumv = wt[ls].sumv + wt[rs].sumv;
    }


    void PushDownUpdate(int rt)
    {
        if(0 != wt[rt].addv)
        {
            int ls = wt[rt].ls;
            int rs = wt[rt].rs;


            Ntype addv = wt[rt].addv;


            wt[ls].addv += addv;
            wt[ls].maxv += addv;
            wt[ls].minv += addv;
            wt[ls].sumv += wt[ls].len * addv;


            wt[rs].addv += addv;
            wt[rs].maxv += addv;
            wt[rs].minv += addv;
            wt[rs].sumv += wt[rs].len * addv;


            wt[rt].addv = 0;
        }
    }


    void build(int rt, int l, int r)
    {
        if(rt > maxrt) maxrt = rt;
 //       printf("(%d,%d,%d)\n", rt, l, r);
        wt[rt].len = r - l + 1;
        wt[rt].lid = l;
        wt[rt].rid = r;
        wt[rt].addv = 0;
        if(l == r)
        {
            wt[rt].ls = -1;
            wt[rt].rs = -1;
            wt[rt].maxv = wt[rt].minv = val[r];
            wt[rt].sumv = wt[rt].maxv;
            return ;
        }
        else
        {
            wt[rt].ls = lson(rt);
            wt[rt].rs = rson(rt);
        }
        int mid = pmid(wt[rt].lid, wt[rt].rid);
        build(lson(rt), l, mid);
        build(rson(rt), mid + 1, r);
        PushUpUpdate(rt);
    }


    void update(int rt, int l, int r, int op, Ntype val)
    {
        if(l <= wt[rt].lid && wt[rt].rid <= r)
        {
            //如果操作为区间增加val
            wt[rt].addv += val;
            wt[rt].maxv += val;
            wt[rt].minv += val;
            wt[rt].sumv += val * wt[rt].len;
            return ;
        }


        if(wt[rt].isLeaf())
        {
            //正常情况是不会进入此判断的
            printf("********正常情况是不会进入此判断的*********\n");
            return ;
        }
        PushDownUpdate(rt);


        int mid = pmid(wt[rt].lid, wt[rt].rid);


        if(l <= mid)
        {
            update(lson(rt), l, r, op, val);
        }
        if(r > mid)
        {
            update(rson(rt), l, r, op, val);
        }
        PushUpUpdate(rt);
    }


    Ntype query(int rt, int l, int r, int op)
    {
        if(l <= wt[rt].lid && wt[rt].rid <= r)
        {
            Ntype res;
            if(1 == op)                 //查询最大值
            {
                res = wt[rt].maxv;
            }
            else if(2 == op)            //查询最小值
            {
                res = wt[rt].minv;
            }
            else if(3 == op)            //查询区间和
            {
                res = wt[rt].sumv;
            }
            return res;
        }
        PushDownUpdate(rt);


        int mid = pmid(wt[rt].lid, wt[rt].rid);


        Ntype res;


        if(l > mid)
        {
            res = query(rson(rt), l, r, op);
        }
        else if(r <= mid)
        {
            res = query(lson(rt), l, r, op);
        }
        else
        {
            if(1 == op)                 //查询最大值
            {
                res = cmax(query(lson(rt), l, r, op), query(rson(rt), l, r, op));
            }
            else if(2 == op)            //查询最小值
            {
                res = cmin(query(lson(rt), l, r, op), query(rson(rt), l, r, op));
            }
            else if(3 == op)            //查询区间和
            {
                res = query(lson(rt), l, r, op) + query(rson(rt), l, r, op);
            }
        }
        return res;
    }


    void printNode(int rt)
    {
        printf("rt = %3d(%3d,%3d) max = %3d min = %3d sum = %3d add = %d\n", rt,  wt[rt].lid, wt[rt].rid, wt[rt].maxv, wt[rt].minv, wt[rt].sumv, wt[rt].addv);
    }


    void printAll()
    {
        for(int i = 1; i <= maxrt; i++)
        {
            if(wt[i].lid > 0)
            {
                printNode(i);
            }
        }
    }
}sTree;


int n, q;
int main()
{


//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);


    while(~scanf("%d %d", &n, &q))
    {
        for(int i = 1; i <= n; i++)
        {
            scanf("%I64d", &sTree.val[i]);
        }
        sTree.build(1, 1, n);


        int a,b,c;
        char ch[10];
        for(;q > 0; q--)
        {
            scanf("%s", ch);
            if('C' == ch[0])
            {
                scanf("%d %d %d", &a, &b, &c);
                sTree.update(1, a, b, 1, c);
            }
            else
            {
                scanf("%d %d", &a, &b);
                printf("%I64d\n", sTree.query(1, a, b, 3));
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值