UVA - 11992 Fast Matrix Operations (线段树)

本文介绍了一种基于线段树的数据结构实现,用于处理二维矩阵的区间更新与查询操作。支持的操作包括区间加值、区间赋值及查询区间和、最小值、最大值。文章通过一个具体的模板代码示例,详细解释了线段树节点的设计、懒惰传播的实现以及更新和查询的方法。

题意:给一个r行c列的矩阵(r<=20,r*l<=1e6),初始化都为0,三种操作:

1 r1 c1 r2 c2 v  把矩阵(r1,c1)到(r2,c2)的元素全加上v

2 r1 c1 r2 c2 v  把矩阵(r1,c1)到(r2,c2)的元素全变成v

3 r1 c1 r2 c2     求矩阵(r1,c1)到(r2,c2)的元素的和、最小值、最大值

这道题简直就是为了让我们写一个线段树基础问题的全能模板啊。。。

也就是 区间双更新(都加上v、都变成v)区间三查询(和、最小值、最大值)模板。

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=4000010;
struct node{
    int addv,setv;
    int sum,ma,mi;
};
int ans,mi,ma,ql,qr;
int x1,x2,v;
struct xds{
    node a[maxn];
void build(int i,int l,int r)
{
    a[i].sum=a[i].ma=a[i].mi=a[i].setv=a[i].addv=0;
    if(l==r)return;
    else
    {
        int mid=(l+r)>>1;
        build(i*2,l,mid);
        build(i*2+1,mid+1,r);
    }
}
void pushup(int i)
{
    a[i].sum=a[i*2].sum+a[i*2+1].sum;
    a[i].ma=max(a[i*2].ma,a[i*2+1].ma);
    a[i].mi=min(a[i*2].mi,a[i*2+1].mi);
}
void pushdown(int i,int l,int r)
{
    if(a[i].setv)
    {
        int x=a[i].setv;
        int mid=(l+r)>>1;
        a[i*2].setv=a[i*2+1].setv=x;
        a[i*2].mi=a[i*2+1].mi=x;
        a[i*2].ma=a[i*2+1].ma=x;
        a[i*2].sum=(mid-l+1)*x;
        a[i*2+1].sum=(r-mid)*x;
        a[i].setv=a[i*2].addv=a[i*2+1].addv=0;
    }
    if(a[i].addv)
    {
        int x=a[i].addv;
        int mid=(l+r)>>1;
        a[i*2].addv+=x;a[i*2+1].addv+=x;
        a[i*2].mi+=x;a[i*2+1].mi+=x;
        a[i*2].ma+=x;a[i*2+1].ma+=x;
        a[i*2].sum+=(mid-l+1)*x;
        a[i*2+1].sum+=(r-mid)*x;
        a[i].addv=0;
    }
}
void update(int i,int l,int r,int id)
{
 if(x1<=l&&x2>=r)
 {
     if(id==1)
     {
         a[i].addv+=v;
         a[i].mi+=v;
         a[i].ma+=v;
         a[i].sum+=(r-l+1)*v;
     }
     else
     {
         a[i].addv=0;
         a[i].setv=v;
         a[i].mi=v;
         a[i].ma=v;
         a[i].sum=(r-l+1)*v;
     }
     return;
 }
 pushdown(i,l,r);
 int mid=(l+r)>>1;
 if(x1<=mid) update(i*2,l,mid,id);
 if(x2>mid) update(i*2+1,mid+1,r,id);
 pushup(i);
}
void query(int i,int l,int r)
{
    if(ql<=l&&qr>=r)
    {
        ans+=a[i].sum;
        ma=max(ma,a[i].ma);
        mi=min(mi,a[i].mi);
        return;
    }
    pushdown(i,l,r);
    int mid=(l+r)>>1;
    if(ql<=mid) query(i*2,l,mid);
    if(qr>mid) query(i*2+1,mid+1,r);
}
}shu[25];
int n,m,k,q;
int b[maxn],tmp,cnt;
int main()
{
    //ios::sync_with_stdio(false);
    int flag;
    int T;
    while(scanf("%d%d%d",&n,&m,&q)!=EOF)
    {
     for(int i=1;i<=n;i++)
     {
         shu[i].build(1,1,m);
     }
        while(q--)
        {
            int id;
            scanf("%d",&id);
            if(id==3){
            int aa,bb;
            ans=0;mi=inf;ma=-inf;
            scanf("%d%d%d%d",&aa,&ql,&bb,&qr);
            for(int j=aa;j<=bb;j++)
            {
                shu[j].query(1,1,m);
            }
            printf("%d %d %d\n",ans,mi,ma);
            }
            else
            {
                int aa,bb;
                scanf("%d%d%d%d%d",&aa,&x1,&bb,&x2,&v);
                for(int j=aa;j<=bb;j++)
                shu[j].update(1,1,m,id);
            }
        }
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值