UVA 11992 快速矩阵操作(线段树区间修改)

对于set操作要清除结点上的addv标记

maintain函数中,先考虑setv再考虑addv

query函数中,综合考虑setv和addv.

#include<bits/stdc++.h>
const int maxn=4e5+10;
const int inf=1000000000;
using namespace std;
int r,c,m,qr,ql;
int _sum,_min,_max;
struct intervaltree{
	int addv[maxn],setv[maxn],sum[maxn],minv[maxn],maxv[maxn];
	void maintain(int node,int l,int r)
	{
		int lc=node<<1,rc=node<<1|1;
		if(r>l){
			sum[node]=sum[lc]+sum[rc];
			minv[node]=min(minv[lc],minv[rc]);
			maxv[node]=max(maxv[lc],maxv[rc]);
		}
		 if(r>l) {
            sum[node]=sum[lc]+sum[rc];
            minv[node]=min(minv[lc],minv[rc]);
            maxv[node]=max(maxv[lc],maxv[rc]);
        }
		if(setv[node]>=0){
			minv[node]=maxv[node]=setv[node];
			sum[node]=setv[node]*(r-l+1);
		}
	 if(addv[node]) {
            minv[node]+=addv[node];
            maxv[node]+=addv[node];
            sum[node]+=addv[node]*(r-l+1);
        }
		
	}

	void pushdown(int node){
		int lc=node<<1,rc=node<<1|1;
		if(setv[node]>=0){
			setv[lc]=setv[rc]=setv[node];
			addv[lc]=addv[rc]=0;
			setv[node]=-1;
		}
		if(addv[node]>0){
			addv[lc]+=addv[node];
			addv[rc]+=addv[node];
			addv[node]=0;
		}		
	}
	void updateset(int node,int l,int r,int v){
		int lc=node<<1,rc=node<<1|1;
		if(ql<=l && qr>=r){
			setv[node]=v;
			addv[node]=0;
		}
		else{
			pushdown(node);
			int m=l+(l-r)/2;
			if(ql<=m) updateset(lc,l,m,v);
			else maintain(lc,l,m);
			if(qr>m)  updateset(rc,m+1,r,v);
			else maintain(rc,m+1,r);			
		}
			maintain(node,l,r);
	}
	void updateadd(int node,int l,int r,int v){
		int lc=node<<1,rc=node<<1|1;
		if(ql<=l && qr>=r){
			addv[node]+=v;
		}
		else{
			pushdown(node);
			int m=l+(r-l)/2;
			if(ql<=m) updateadd(lc,l,m,v);
			else maintain(lc,r,m);
			if(qr>m) updateadd(rc,m+1,r,v);
			else maintain(rc,m+1,r);			
		}
		maintain(node,l,r);
	}
 
void query(int node,int l,int r,int add)
    {
        if(setv[node]>=0) {
            int v=add+addv[node]+setv[node];
            _sum+=(min(qr,r)-max(l,ql)+1)*v;
            _min=min(_min,v);
            _max=max(_max,v);
        }
        else if(ql<=l&&qr>=r) {
            _sum+=sum[node]+add*(r-l+1);
            _min=min(_min,minv[node]+add);
            _max=max(_max,maxv[node]+add);
        }
        else {
            int m=l+(r-l)/2;
            if(ql<=m)
            query(node<<1,l,m,add+addv[node]);
            if(qr>m)
            query(node<<1|1,m+1,r,add+addv[node]);
        }
 
    }

	
};



intervaltree tree[25];

int main(){
	while(scanf("%d %d %d",&r,&c,&m)!=EOF){
	 memset(tree,0,sizeof tree);
        for(int i = 1; i <= r;++i) {
            memset(tree[i].setv, -1, sizeof(tree[i].setv));
            tree[i].setv[1] = 0;
        }
		int op,x1,x2,v;
	
		    while(m--) {
            _sum=0;
            _min=inf;
            _max=0;
            scanf("%d%d%d%d%d",&op,&x1,&ql,&x2,&qr);
            //if(x1>x2) swap(x1,x2);
            if(op==1||op==2) {
                scanf("%d",&v);
                if(op==1) {
                    for(int i = x1;i<=x2;++i) {
                        tree[i].updateadd(1,1,c,v);
                    }
                }
                else {
                     for(int i = x1;i<=x2;++i) {
                        tree[i].updateset(1,1,c,v);
                    }
                }
            }
            else {
                for(int i=x1;i<=x2;++i) {
                    tree[i].query(1,1,c,0);
                }
                printf("%d %d %d\n",_sum,_min,_max);
 
            }
        }
	}
		return 0;
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值