UVA 11992 Fast Matrix Operations

题目链接:UVA 11992 Fast Matrix Operations


分析:

其实这题只用把矩阵完全看成一维的一排数,开一个数组建一个线段树,就行了。然而我却傻傻的每行开了一个线段树,代码有点丑,不要在意。

主要是set操作和Add操作之间的关系要搞清楚。

因为始终是先处理set再处理add,所以set标记传递的时候必须把add标记改为0(代码中有注释),这里很容易忘掉,导致WA。

还有add标记的初值是0(反倒不能弄成-1),Set标记的初值是-1,这两个都很容易错。

代码如下:

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#define CLEAR(xxx) memset(xxx,0,sizeof(xxx))
using namespace std;
const int maxn=1000000+5,inf=1e9;

template <typename T>
inline void _read(T &x){
	char ch=getchar(); bool mark=false;
	for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;
	for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';
	if(mark)x=-x;
}

int r,c,m,x1,y1,x2,y2;
int maxv[maxn*4][21],minv[maxn*4][21],sum[maxn*4][21]; 
int lazy[maxn*4][21],addv[maxn*4][21];

void pushdown(int o,int L,int R,int id){
	int ls=o<<1,rs=ls+1,mid=(L+R)>>1;
	if(lazy[o][id]!=-1){
		addv[ls][id]=addv[rs][id]=0;  //这里很重要 
		maxv[ls][id]=maxv[rs][id]=lazy[o][id];
		minv[ls][id]=minv[rs][id]=lazy[o][id];
		lazy[ls][id]=lazy[rs][id]=lazy[o][id];
		sum[ls][id]=(mid-L+1)*lazy[o][id];
		sum[rs][id]=(R-mid)*lazy[o][id];
		lazy[o][id]=-1;
	}
	if(addv[o][id]){
		maxv[ls][id]+=addv[o][id];
		minv[ls][id]+=addv[o][id];
		maxv[rs][id]+=addv[o][id];
		minv[rs][id]+=addv[o][id];
		sum[ls][id]+=(mid-L+1)*addv[o][id];
		sum[rs][id]+=(R-mid)*addv[o][id];
	    addv[ls][id]+=addv[o][id];
	    addv[rs][id]+=addv[o][id];
		addv[o][id]=0;
	}
}

void Maintain(int o,int id){
	maxv[o][id]=max(maxv[o<<1][id],maxv[o*2+1][id]);
	minv[o][id]=min(minv[o<<1][id],minv[o*2+1][id]);
	sum[o][id]=sum[o<<1][id]+sum[o*2+1][id];
}

void Update(int o,int L,int R,int v,int id){
	if(lazy[o][id]!=-1||addv[o][id])pushdown(o,L,R,id);
	if(y1<=L&&y2>=R){
		maxv[o][id]+=v;
		minv[o][id]+=v;
		sum[o][id]+=(R-L+1)*v;
		addv[o][id]+=v;
		return ;
	}
	int mid=(L+R)>>1;
	if(y1<=mid) Update(o<<1,L,mid,v,id);
	if(y2>mid) Update(o*2+1,mid+1,R,v,id);
	Maintain(o,id);
}

void update(int o,int L,int R,int v,int id){
	if(lazy[o][id]!=-1||addv[o][id])pushdown(o,L,R,id);
	if(y1<=L&&y2>=R){
		maxv[o][id]=v;
		minv[o][id]=v;
		sum[o][id]=v*(R-L+1);
		lazy[o][id]=v; addv[o][id]=0;
		return ;
	}
	int mid=(L+R)>>1;
	if(y1<=mid) update(o<<1,L,mid,v,id);
	if(y2>mid) update(o*2+1,mid+1,R,v,id);
	Maintain(o,id);
}

int Query(int o,int L,int R,int id){    //Max
	if(lazy[o][id]!=-1||addv[o][id]) pushdown(o,L,R,id);
	if(y1<=L&&y2>=R) return maxv[o][id];
	int Max=0,mid=(L+R)>>1;
	if(y1<=mid) Max=max(Max,Query(o<<1,L,mid,id));
	if(y2>mid)  Max=max(Max,Query(o*2+1,mid+1,R,id));
	return Max;
}

int query(int o,int L,int R,int id){   //Min 
	if(lazy[o][id]!=-1||addv[o][id]) pushdown(o,L,R,id);
	if(y1<=L&&y2>=R) return minv[o][id];
	int Min=inf,mid=(L+R)>>1;
	if(y1<=mid) Min=min(Min,query(o<<1,L,mid,id));
	if(y2>mid)  Min=min(Min,query(o*2+1,mid+1,R,id));
	return Min;
}

int Getsum(int o,int L,int R,int id){  
	if(lazy[o][id]!=-1||addv[o][id]) pushdown(o,L,R,id);
	if(y1<=L&&y2>=R) return sum[o][id];
	int Sum=0,mid=(L+R)>>1;
	if(y1<=mid) Sum+=Getsum(o<<1,L,mid,id);
	if(y2>mid) Sum+=Getsum(o*2+1,mid+1,R,id);
	return Sum;
}

void Solve(){
	int op,v,i;
	_read(c);_read(m);
	CLEAR(maxv); CLEAR(minv); CLEAR(addv);CLEAR(sum);
	memset(lazy,-1,sizeof(lazy));
	while(m--){
		_read(op);
		_read(x1); _read(y1);_read(x2); _read(y2);
		if(op==1){   //Add
			_read(v);
		    for(i=x1;i<=x2;i++)Update(1,1,c,v,i); 
		}
		else if(op==2){
			_read(v);
			for(i=x1;i<=x2;i++)	update(1,1,c,v,i);
		}
		else {
			int Max=0,Min=inf,Sum=0;
			for(i=x1;i<=x2;i++){
				Max=max(Max,Query(1,1,c,i));
				Min=min(Min,query(1,1,c,i));
				Sum+=Getsum(1,1,c,i);
			}
			printf("%d %d %d\n",Sum,Min,Max);
		}
	}
} 

int main(){
	while(cin>>r)Solve();
	return 0;
}






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值