UVA11992--Fast Matrix Operations

题意:一个r*c的矩阵,初始值全部为0,后进行三种操作,
1 子矩阵[x1,y1]--[x2,y2]所有元素+v,
2 子矩阵[x1,y1][x2,y2]所有元素变为v
3 输出子矩阵[x1,y1][x2,y2]的所有元素和,最小值,最大值

思路:一个线段树,不知道哪里来的条件是r<=20..所以第一维可以直接暴力循环更改查找。。单独的修改区间元素值和区间加值。都是会的,两个连在一起也不是很难,就是有点复杂。。。函数嵌套
感想:到现在不知道条件r<=20哪里来的。。。当然这题是看的题解,不然真的不知道怎么做。。。最后,这个题按着r<=20的前提来暴力做并不很难,就是复杂,所以代码就看了一下,也不敲了,加了两句注释。。。
代码:
#include<bits/stdc++.h>
#define MAX 3000100
using namespace std;
struct node
{
    int l,r;
    int mini,maxi,sum;
    int add,set;
}a[MAX];
int anssum,ansmin,ansmax,r,c,m;
const int inf=1000000009;
void built(int l,int r,int index)///建树
{
    a[index].l=l;a[index].r=r;a[index].add=0;a[index].set=-1;a[index].sum=a[index].mini=a[index].maxi=0;
    if(l==r)
	return;
    int mid=l+(r-l)/2;
    built(l,mid,index<<1);built(mid+1,r,index<<1|1);
}
void pushdown(int index)///更新子节点
{
    if(a[index].l>=a[index].r)
	return;
    if(a[index].set!=-1)
    {
	a[index<<1].set=a[index<<1|1].set=a[index].set;
	a[index<<1].mini=a[index<<1|1].mini=a[index].set;
	a[index<<1].maxi=a[index<<1|1].maxi=a[index].set;
	a[index<<1].add=a[index<<1|1].add=0;
	a[index<<1].sum=(a[index<<1].r-a[index<<1].l+1)*a[index].set;
	a[index<<1|1].sum=(a[index<<1|1].r-a[index<<1|1].l+1)*a[index].set;
    }
    if(a[index].add>0)
    {
	int ita=a[index].add;
	a[index<<1].add+=ita;a[index<<1|1].add+=ita;
	a[index<<1].mini+=ita;a[index<<1|1].mini+=ita;
	a[index<<1].maxi+=ita;a[index<<1|1].maxi+=ita;
	a[index<<1].sum+=ita*(a[index<<1].r-a[index<<1].l+1);
	a[index<<1|1].sum+=ita*(a[index<<1|1].r-a[index<<1|1].l+1);
    }
}
void maintain(int index)///更新当前节点
{
    if(a[index].l>=a[index].r)
	return;
    a[index].maxi=max(a[index<<1].maxi,a[index<<1|1].maxi);
    a[index].mini=min(a[index<<1].mini,a[index<<1|1].mini);
    a[index].sum=a[index<<1].sum+a[index<<1|1].sum;
}
void updateSet(int L,int R,int val,int index) ///区间赋新值,更新树
{
    if(a[index].l==L&&a[index].r==R)
    { 
	a[index].set=val;
	a[index].maxi=val;
	a[index].mini=val;
	a[index].add=0;
	a[index].sum=(a[index].r-a[index].l+1)*val;
	return;
    }
    pushdown(index);
    a[index].set=-1;
    a[index].add=0;
    int mid=a[index].l+(a[index].r-a[index].l)/2;
    if(R<=mid)
	updateSet(L,R,val,index<<1);
    else if(L>mid)
	updateSet(L,R,val,index<<1|1);
    else
    {
	updateSet(L,mid,val,index<<1);
	updateSet(mid+1,R,val,index<<1|1);
    }
    maintain(index);
}
void updateAdd(int L,int R,int val,int index)///区间加值,更新树
{
    if(a[index].l==L&&a[index].r==R)
    {
	a[index].add+=val;
	a[index].maxi+=val;
	a[index].mini+=val;
	a[index].sum+=(a[index].r-a[index].l+1)*val;
	return ;
    }
    pushdown(index);
    a[index].set=-1;
    a[index].add=0;
    int mid=a[index].l+(a[index].r-a[index].l)/2;
    if(R<=mid)
	updateAdd(L,R,val,index<<1);
    else if(L>mid)
	updateAdd(L,R,val,index<<1|1);
    else
    {
        updateAdd(L,mid,val,index<<1);
        updateAdd(mid+1,R,val,index<<1|1);
    }
    maintain(index);
}
void Query(int L,int R,int index)///查找区间最值与和
{
    if(a[index].l==L&&a[index].r==R)
    {
        anssum+=a[index].sum;
        ansmin=min(ansmin,a[index].mini);
        ansmax=max(ansmax,a[index].maxi);
        return;
    }
    pushdown(index);
    a[index].set=-1;
    a[index].add=0;
    int mid=a[index].l+(a[index].r-a[index].l)/2;
    if(R<=mid)
	Query(L,R,index<<1);
    else if(L>mid)
	Query(L,R,index<<1|1);
    else
    {
	Query(L,mid,index<<1);
	Query(mid+1,R,index<<1|1);
    }
    maintain(index);
}
int main()
{
    while(scanf("%d%d%d",&r,&c,&m)!=EOF)
    {
	built(1,r*c,1);
	int op,x1,x2,y1,y2,val;
	while(m--)
	{
	    scanf("%d",&op);
	    if(op==1)
	    {
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
		for(int i=x1;i<=x2;i++)
		    updateAdd((i-1)*c+y1,(i-1)*c+y2,val,1);
	    }
	    else if(op==2)
	    {
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
		for(int i=x1;i<=x2;i++)
		    updateSet((i-1)*c+y1,(i-1)*c+y2,val,1);
	    }
	    else
	    {
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		anssum=0;ansmin=inf;ansmax=-inf;
		for(int i=x1;i<=x2;i++)
		    Query((i-1)*c+y1,(i-1)*c+y2,1);
		printf("%d %d %d\n",anssum,ansmin,ansmax);
	    }
	}
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值