二维线段树(uva11992)

封装一个线段树包含

维护信息,标记,maintain,pushdown,update,query操作

#include<bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
using namespace std;
const int N=1<<18;
const int inf=1e9+5;
int _max,_sum,_min,op,x,y,x2,y2,v,r,c,m,i,j;
struct tree{
    int sum[N],maxx[N],minn[N],add_tag[N],set_tag[N];
    void maintain(int p,int l ,int r)
    {
        if(r>l)
        {
            sum[p]=sum[ls]+sum[rs];
            maxx[p]=max(maxx[ls],maxx[rs]);
            minn[p]=min(minn[ls],minn[rs]);
        }
        if(set_tag[p]!=-1)
        {
          maxx[p]=set_tag[p],minn[p]=set_tag[p],sum[p]=set_tag[p]*(r-l+1);
        }
        if(add_tag[p])
        {
            minn[p]+=add_tag[p];
            maxx[p]+=add_tag[p];
            sum[p]+=add_tag[p]*(r-l+1);
        }
    }
    void push_down(int p)
    {
        if(set_tag[p]!=-1)
        {
            set_tag[ls]=set_tag[rs]=set_tag[p];
            add_tag[ls]=add_tag[rs]=0;
            set_tag[p]=-1;
        }
        if(add_tag[p])
        {
            add_tag[ls]+=add_tag[p];
            add_tag[rs]+=add_tag[p];
            add_tag[p]=0;
        }
    }
    void update(int p,int l,int r)
    {
        if(y<=l&&r<=y2)
        {
            if(op==1)
                add_tag[p]+=v;
            else add_tag[p]=0,set_tag[p]=v;
        }
        else {
            push_down(p);
            int m=(l+r)>>1;
            if(y<=m) update(ls,l,m);
            else maintain(ls,l,m);
            if(y2>m) update(rs,m+1,r);
            else maintain(rs,m+1,r);
            
        }
        maintain(p,l,r);
    }
    void queryy(int p,int l,int r,int& ssum,int& smin,int& smax)
    {
        maintain(p,l,r);
        
        if(y<=l&&r<=y2)
        {
            ssum=sum[p];
            smax=maxx[p];
            smin=minn[p];
        }
        else {
            push_down(p);
            int m=(l+r)>>1;
            int lsum=0,lmin=inf,lmax=-inf;
            int rsum=0,rmin=inf,rmax=-inf;
            if(y<=m)
                queryy(ls,l,m,lsum,lmin,lmax);
            else maintain(ls,l,m);
            if(y2>m)
                queryy(rs,m+1,r,rsum,rmin,rmax);
            else maintain(rs,m+1,r);
            ssum=lsum+rsum;
            smin=min(lmin,rmin);
            smax=max(lmax,rmax);
        }
    }
}trees[21];

int main ()
{
    while(scanf("%d%d%d",&r,&c,&m)==3)
    {
        memset(trees,0,sizeof(trees));
        for(i=1;i<=r;++i)
        {
            memset(trees[i].set_tag,-1,sizeof(trees[i].set_tag));
                trees[i].set_tag[1]=0;
        }
        for(i=1;i<=m;++i)
        {
            scanf("%d%d%d%d%d",&op,&x,&y,&x2,&y2);
            if(op!=3)
            {
                scanf("%d",&v);
                for(j=x;j<=x2;++j)
                {
                    trees[j].update(1,1,c);
                }
            }
            else {
                _max=-inf;
                _min=inf;
                _sum=0;
                int gmax=-inf,gmin=inf,gsum=0;
                for(j=x;j<=x2;++j)
                {
                    trees[j].queryy(1,1,c,_sum,_min,_max);
                    gsum+=_sum;
                    gmax=max(_max,gmax);
                    gmin=min(_min,gmin);
                    _sum=0,_max=-inf,_min=inf;
                }
                printf("%d %d %d\n",gsum,gmin,gmax);
            }
        }
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值