UVA 11992 Fast Matrix Operations 线段树

本文介绍了解决UVA11992问题的算法思路,使用20个线段树来处理矩阵操作,包括修改和查询操作,详细展示了线段树的构建、更新、下传和查询过程。

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

UVA 11992

对矩阵操作我们容易想到二维线段树或者二维树状数组

但是这题不需要二维 由于r<=20 所以我们开20个线段树就可以记录了 不过要注意一下set和add的先后顺序即可

#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
#include <queue>
#include <map>
#include <sstream>
#include <set>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAX_N = 100005;
int add[25][MAX_N<<1],col[25][MAX_N<<1],s[25][MAX_N<<1],minn[25][MAX_N<<1],maxx[25][MAX_N<<1];
void up(int p,int rt){
    s[p][rt] = s[p][rt<<1] + s[p][rt<<1|1];
    maxx[p][rt] = max(maxx[p][rt<<1],maxx[p][rt<<1|1]);
    minn[p][rt] = min(minn[p][rt<<1],minn[p][rt<<1|1]);
}
void build(int p,int rt,int l,int r){
    col[p][rt] = add[p][rt] = 0;
    if(l==r){
        s[p][rt] =maxx[p][rt] = minn[p][rt] = 0;
        return;
    }
    int mid = (l+r)>>1;
    build(p,rt<<1,l,mid);
    build(p,rt<<1|1,mid+1,r);
}
void down(int p,int rt,int l,int r){
    int mid = (l+r)>>1;
    if(col[p][rt]){
        col[p][rt<<1] = col[p][rt];
        maxx[p][rt<<1] = col[p][rt];
        minn[p][rt<<1] = col[p][rt];
        s[p][rt<<1] = (mid-l+1)*col[p][rt];
        add[p][rt<<1] = 0;

        col[p][rt<<1|1] = col[p][rt];
        maxx[p][rt<<1|1] = col[p][rt];
        minn[p][rt<<1|1] = col[p][rt];
        s[p][rt<<1|1] = (r-mid)*col[p][rt];
        add[p][rt<<1|1] = 0;

        col[p][rt] = 0;
    }
    if(add[p][rt]){
        add[p][rt<<1] += add[p][rt];
        minn[p][rt<<1]+=add[p][rt];
        maxx[p][rt<<1]+=add[p][rt];
        s[p][rt<<1] += add[p][rt]*(mid-l+1);

        add[p][rt<<1|1] += add[p][rt];
        minn[p][rt<<1|1] += add[p][rt];
        maxx[p][rt<<1|1] += add[p][rt];
        s[p][rt<<1|1] += add[p][rt]*(r-mid);

        add[p][rt] = 0;
    }
}
void modify(int opt,int p,int rt,int l,int r,int x,int y,int v){
    if(opt==1){
        if(x<=l&&r<=y){
            add[p][rt] += v;
            maxx[p][rt] += v;
            minn[p][rt] += v;
            s[p][rt] += (r-l+1)*v;
            return ;
        }
        int mid = (l+r)>>1;
        down(p,rt,l,r);
        if(x<=mid) modify(opt,p,rt<<1,l,mid,x,y,v);
        if(mid<y) modify(opt,p,rt<<1|1,mid+1,r,x,y,v);
        up(p,rt);
    }
    else {
        if(x<=l&&r<=y){
            col[p][rt] = v;
            minn[p][rt] = v;
            maxx[p][rt] = v;
            s[p][rt] = (r-l+1)*v;
            add[p][rt] = 0;
            return ;
        }
        int mid = (l+r)>>1;
        down(p,rt,l,r);
        if(x<=mid) modify(opt,p,rt<<1,l,mid,x,y,v);
        if(mid<y) modify(opt,p,rt<<1|1,mid+1,r,x,y,v);
        up(p,rt);
    }
}
int query(int p,int rt,int l,int r,int x,int y){
    if(x<=l&&r<=y){
        return maxx[p][rt];
    }
    int mid = (l+r)>>1;
    down(p,rt,l,r);
    int maxx1 = 0,maxx2 = 0;
    if(x<=mid) maxx1 = query(p,rt<<1,l,mid,x,y);
    if(mid<y) maxx2 = query(p,rt<<1|1,mid+1,r,x,y);
    return max(maxx1,maxx2);
}
int query_(int p,int rt,int l,int r,int x,int y){
    if(x<=l&&r<=y){
        return minn[p][rt];
    }
    int mid = (l+r)>>1;
    down(p,rt,l,r);
    int minn1 = 0x3f3f3f3f,minn2 = 0x3f3f3f3f;
    if(x<=mid) minn1 = query_(p,rt<<1,l,mid,x,y);
    if(mid<y) minn2 = query_(p,rt<<1|1,mid+1,r,x,y);
    return min(minn1,minn2);
}
int query_sum(int p,int rt,int l,int r,int x,int y){
    if(x<=l&&r<=y)
        return s[p][rt];
    int mid = (l+r)>>1;
    down(p,rt,l,r);
    int sum = 0;
    if(x<=mid) sum+=query_sum(p,rt<<1,l,mid,x,y);
    if(mid<y) sum+=query_sum(p,rt<<1|1,mid+1,r,x,y);
    return sum;
}
int ansmin,ansmax,anssum;

void Query(int p,int rt,int l,int r,int x,int y){
    if(x<=l&&r<=y){
        ansmin = min(ansmin,minn[p][rt]);
        ansmax = max(ansmax,maxx[p][rt]);
        anssum += s[p][rt];
        return ;
    }
    down(p,rt,l,r);
    int mid = (l+r)>>1;
    if(x<=mid) Query(p,rt<<1,l,mid,x,y);
    if(mid<y) Query(p,rt<<1|1,mid+1,r,x,y);
}
int main(){
    int n,m,q;
    while(scanf("%d%d%d",&n,&m,&q)==3){
        for(int i = 1;i<=n;++i)
            build(i,1,1,m);
        while(q--){
            int opt,a,b,c,d,v;
            scanf("%d",&opt);
            if(opt==1){
                scanf("%d%d%d%d%d",&a,&b,&c,&d,&v);
                for(int i = a;i<=c;++i)
                    modify(opt,i,1,1,m,b,d,v);
            }
            else if(opt==2){
                scanf("%d%d%d%d%d",&a,&b,&c,&d,&v);
                for(int i = a;i<=c;++i)
                    modify(opt,i,1,1,m,b,d,v);
            }
            else if(opt==3){
                scanf("%d%d%d%d",&a,&b,&c,&d);
                //ansmin= 0x3f3f3f3f,ansmax = 0,anssum = 0;
                int a_maxx = 0,a_minn = 0x3f3f3f3f,a_sum = 0;
                for(int i = a;i<=c;++i){
                    a_maxx = max(a_maxx,query(i,1,1,m,b,d));
                    a_minn = min(a_minn,query_(i,1,1,m,b,d));
                    a_sum+=query_sum(i,1,1,m,b,d);
                    //Query(i,1,1,m,b,d);
                }
                printf("%d %d %d\n",a_sum,a_minn,a_maxx);
            }
        }
    }
    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值