线段树--区间修改set,区间更新add


#include <iostream>

#include <cstdio>

#include <cstring>

using namespacestd;


const int maxn =1e6 + 5;

const int INF =1 << 30;


int ql,qr,op;

int x1,x2,v;

int _sum,_min,_max;

struct tree{

    struct node{

        int minv,maxv,sumv;

        int add,set;

    }seg[maxn <<2];

    void pushup(int l,int r,int rt)

    {

        int lc = rt <<1,rc = lc | 1;

        seg[rt].minv =min(seg[lc].minv,seg[rc].minv);

        seg[rt].maxv =max(seg[lc].maxv,seg[rc].maxv);

        seg[rt].sumv =seg[lc].sumv +seg[rc].sumv;

    }

    void pushdown(int l,int r,int rt)

    {

        int lc = rt <<1,rc = lc | 1;

        int mid = (l + r) >>1;

        if(seg[rt].set){//v > 0

            int x =seg[rt].set;

            seg[lc].set =seg[rc].set = x;

            seg[lc].maxv =seg[rc].maxv = x;

            seg[lc].minv =seg[rc].minv = x;

            seg[lc].sumv = (mid - l +1) * x;seg[rc].sumv = (r - mid) * x;

            seg[rt].set =seg[lc].add =seg[rc].add =0;//set时,add就失效,变成0

        }

        if(seg[rt].add){

            int x =seg[rt].add;

            seg[lc].add += x;seg[rc].add += x;

            seg[lc].maxv += x;seg[rc].maxv += x;

            seg[lc].minv += x;seg[rc].minv += x;

            seg[lc].sumv += (mid - l +1) * x;seg[rc].sumv += (r - mid) * x;

            seg[rt].add =0;

        }

    }

    void update(int l,int r,int rt)

    {

        if(ql <= l && r <=qr){

            if(op ==1){

                seg[rt].add +=v;

                seg[rt].minv +=v;

                seg[rt].maxv +=v;

                seg[rt].sumv += (r - l +1) * v;

            }

            else{

                seg[rt].set =seg[rt].minv =seg[rt].maxv =v;

                seg[rt].sumv = (r - l +1) * v;

                seg[rt].add =0;

            }

            return;

        }

        pushdown(l, r, rt);

        int mid = (l + r) >>1;

        if(ql <= mid)update(l, mid, rt << 1);

        if(mid <qr) update(mid +1, r, rt << 1 |1);

        pushup(l, r, rt);

    }

    void query(int l,int r,int rt)

    {

        if(ql <= l && r <=qr){

            _sum +=seg[rt].sumv;

            _min =min(_min,seg[rt].minv);

            _max =max(_max,seg[rt].maxv);

            return;

        }

        pushdown(l, r, rt);

        int mid = (l + r) >>1;

        if(ql <= mid)query(l, mid, rt << 1);

        if(mid <qr) query(mid +1, r, rt << 1 |1);

    }

}trees[22];



int main()

{

    int r,c,m;

    while (scanf("%d%d%d",&r,&c,&m) !=EOF) {


        memset(trees,0, sizeof(trees));

        for (int i =0; i < m; i ++) {

            scanf("%d%d%d%d%d",&op,&x1,&ql,&x2,&qr);

            if(op <3){

                scanf("%d",&v);

                for (int j =x1; j <= x2; j ++) {

                    trees[j].update(1, c,1);

                }

            }

            else{

                _sum =0,_max = -INF,_min =INF;

                for (int j =x1; j <= x2; j ++) {

                    trees[j].query(1, c,1);

                }

                printf("%d %d %d\n",_sum,_min,_max);

            }

        }

    }

    return0;

}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值