UVA 11992 Fast MatrixOperations(线段树)

本文介绍了一种使用线段树解决二维矩阵操作问题的方法,包括子矩阵元素的增加、替换以及查询子矩阵的最大值、最小值和总和。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给你一个一开始全为0的矩阵,有三种操作,子矩阵全部增加一个数,子矩阵替换一个数,查询子矩阵之和和最大最小值

思路:显然的线段树,留意到这个矩阵最多只有20行,所以每一行都建一颗线段树即可


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn = 1000010;
const int INF = 1e9;
#define lson i*2,l,m
#define rson i*2+1,m+1,r
int r,c,m;
int amax[22],amin[22],asum[22];
int setv[maxn*5],addv[maxn*5],sum[maxn*5],minv[maxn*5],maxv[maxn*5];
void build(int k,int i,int l,int r)
{
	int t = k*4*c;
	setv[t+i]=-1;
	addv[t+i]=sum[t+i]=minv[t+i]=maxv[t+i]=0;
	if (l==r)
		return;
	int m = (l+r)>>1;
	build(k,lson);
	build(k,rson);
}

void PushDown(int k,int i,int l,int r)
{
	int t = k*4*c;
	int m = (l+r)>>1;
	if (setv[t+i]!=-1)
	{
		if (l!=r)
		{
			addv[t+i*2]=addv[t+i*2+1]=0;
			setv[t+i*2]=setv[t+i*2+1]=setv[t+i];
			sum[t+i*2]=setv[t+i]*(m-l+1);
			sum[t+i*2+1]=setv[t+i]*(r-m);
			maxv[t+i*2]=minv[t+i*2]=maxv[t+i*2+1]=minv[t+i*2+1]=setv[t+i];
		}
		setv[t+i]=-1;
	}
	if (addv[t+i]>0)
	{
		if (l!=r)
		{
			addv[t+i*2]+=addv[t+i];
			addv[t+i*2+1]+=addv[t+i];
			sum[t+i*2]+=addv[t+i]*(m-l+1);
			maxv[t+i*2]+=addv[t+i];
			minv[t+i*2]+=addv[t+i];
			sum[t+i*2+1]+=addv[t+i]*(r-m);
			maxv[t+i*2+1]+=addv[t+i];
			minv[t+i*2+1]+=addv[t+i];
		}
		addv[t+i]=0;
	}
}

void PushUp(int k,int i,int l,int r)
{
	int t = k*4*c;
	sum[t+i]=sum[t+i*2]+sum[t+i*2+1];
	maxv[t+i]=max(maxv[t+i*2],maxv[t+i*2+1]);
	minv[t+i]=min(minv[t+i*2],minv[t+i*2+1]);
}
void update_add(int k,int ql,int qr,int v,int i,int l,int r)
{
    int t = k*4*c;
	if (ql<=l && r<=qr)
	{
		addv[t+i]+=v;
		sum[t+i]+=v*(r-l+1);
		maxv[t+i]+=v;
		minv[t+i]+=v;
		return;
	}
	PushDown(k,i,l,r);
	int m = (l+r)>>1;
	if (ql<=m)
		update_add(k,ql,qr,v,lson);
	if (m<qr)
		update_add(k,ql,qr,v,rson);
	PushUp(k,i,l,r);
}

void update_set(int k,int ql,int qr,int v,int i,int l,int r)
{
	int t = k*4*c;
	if (ql<=l && qr>=r)
	{
		setv[t+i]=v;
		addv[t+i]=0;
		sum[t+i]=v*(r-l+1);
		maxv[t+i]=minv[t+i]=v;
		return;
	}
	PushDown(k,i,l,r);
    int m = (l+r)>>1;
	if (ql<=m)
		update_set(k,ql,qr,v,lson);
	if (m<qr)
		update_set(k,ql,qr,v,rson);
	PushUp(k,i,l,r);
}
void query(int k,int ql,int qr,int i,int l,int r)
{
	int t =4*c*k;
	if (ql<=l && qr>=r)
	{
		asum[k]+=sum[t+i];
		amin[k]=min(amin[k],minv[t+i]);
		amax[k]=max(amax[k],maxv[t+i]);
		return;
	}
	PushDown(k,i,l,r);
	int m = (l+r)>>1;
	if (ql<=m)
		query(k,ql,qr,lson);
	if (m<qr)
		query(k,ql,qr,rson);
}

int main()
{
	while (scanf("%d%d%d",&r,&c,&m)!=EOF)
	{
		for (int i = 1;i<=r;i++)
			build(i,1,1,c);
		while (m--)
		{
			int op,x1,x2,y1,y2,v;
			scanf("%d%d%d%d%d",&op,&x1,&y1,&x2,&y2);
			if (op!=3)
				scanf("%d",&v);
			if (op==1)
			{
				for (int i = x1;i<=x2;i++)
					update_add(i,y1,y2,v,1,1,c);
			}
			else if (op==2)
			{
				for (int i = x1;i<=x2;i++)
					update_set(i,y1,y2,v,1,1,c);
			}
			else if (op==3)
			{
				memset(asum,0,sizeof(asum));
				for (int i = 0;i<=r;i++)
				{
					amax[i]=-INF;
					amin[i]=INF;
				}
				int sum_v=0,max_v=-INF,min_v=INF;
				for (int i = x1;i<=x2;i++)
				{
					query(i,y1,y2,1,1,c);
					sum_v+=asum[i];
					max_v=max(max_v,amax[i]);
					min_v=min(min_v,amin[i]);
				}
				printf("%d %d %d\n",sum_v,min_v,max_v);
			}
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值