UVA11992 - Fast Matrix Operations

 

 

#include <iostream>
#include "stdio.h"
#include <memory.h>
#include <algorithm>

const int MAX = 2000000 + 10,MAX_R = 20+5,MAX_SUM = 1000000000 + 10;
int set[MAX_R][MAX],add[MAX_R][MAX],sum[MAX_R][MAX],mmax[MAX_R][MAX],mmin[MAX_R][MAX];


using namespace std;
int L,R;
int t,x1,y1,x2,y2,v;
int r,c,m;
int mi,mx,su;

void push_down(int row, int o)
{
    if(set[row][o] >= 0)
    {
        set[row][o * 2] = set[row][o * 2 + 1] = set[row][o];
        add[row][o * 2] = add[row][o * 2 + 1] = 0;
        set[row][o] = -1;
    }

    if(add[row][o] > 0)
    {
        add[row][o * 2] += add[row][o];
        add[row][o * 2 + 1] += add[row][o];
        add[row][o] = 0;
    }
}

void maintain(int row, int o, int l, int r)
{

    if(set[row][o] >= 0)
    {
        sum[row][o] = (set[row][o] + add[row][o]) * (r - l + 1);
        mmin[row][o] = mmax[row][o] = set[row][o] + add[row][o];
    }
    else if(r > l)//非叶子结点
    {
        sum[row][o] = sum[row][o * 2] + sum[row][o * 2 + 1] + (r - l + 1) * add[row][o]  ;
        mmax[row][o] = max(mmax[row][o * 2], mmax[row][o * 2 + 1]) + add[row][o];
        mmin[row][o] = min(mmin[row][o * 2], mmin[row][o * 2 + 1]) + add[row][o];
    }
    else{
        sum[row][o] = mmax[row][o] = mmin[row][o] = add[row][o];
    }

//    sum
//
//    sum[row][o] = (r - l + 1) * set[row][o];
//    mmin[row][o] = mmax[row][o] = set[row][o];
//    add[row][o] = 0;
}

void updata(int row,int o, int l, int r,int v)
{
    if(L <= l && R >= r)
    {
        //cout << l<<"--"<<r<<endl;
        if(t == 1)
            add[row][o] += v;
        else
        {
            add[row][o] = 0;
            set[row][o] = v;//cout <<"set row==>"<<row<<"l =>"<<l<<" r==>"<<r<< "set==>"<<set[row][o]<<endl;
        }
    }
    else
    {
        push_down(row, o);

        int M = l + (r - l) / 2;
        if(L <= M)updata(row, o * 2, l, M, v);
        else maintain(row, o * 2, l, M);

        if(R > M)updata(row, o * 2 + 1, M + 1, r, v);
        else maintain(row, o * 2 + 1, M + 1, r);
    }

    maintain(row, o, l, r);
}




void query_row(int row, int o, int l, int r, int adds)
{
    if(o == 1){su = 0;}


    if(L <= l && R >= r)//叶子节点一定满足
    {
        if(set[row][o] >= 0)
        {
            //cout <<"row==>"<<row<<"l =>"<<l<<" r==>"<<r<< "set==>"<<set[row][o]<<endl;
            l = max(l, L); r = min(r, R);
            su += (r - l + 1) * set[row][o] + (r - l + 1) * adds;
            mi = min(mi, mmin[row][o] + adds);
            mx = max(mx, mmax[row][o] + adds);
        }
        else
        {
            su += sum[row][o] + (r - l + 1) * adds;
            mi = min(mi, mmin[row][o] + adds);
            mx = max(mx, mmax[row][o] + adds);
        }

        //cout<<"query_row:"<<row<<"  "<<l<<"=="<<r<<"  L:"<<L<<"  R:"<<R<<" sum:"<<su<<" max"<<mx<<" min:"<<mi<<endl;

    }
    else
    {
        int M = l + (r - l) / 2;
        adds += add[row][o];

        if(L <= M)query_row(row, o * 2, l, M, adds);
        if(R > M)query_row(row, o * 2 + 1, M + 1, r, adds);
    }


}

void updatas(int x1,int y1,int x2,int y2,int v)
{
    L = x1; R = x2;
    for(int i = y1; i <= y2; i++)
    {
        updata(i, 1, 1, c, v);
    }
}



void query(int x1,int y1, int x2, int y2)
{
    L = x1; R = x2;
    int rtv_sum = 0;

    mi = MAX_SUM; mx = 0;
    for(int i = y1; i <= y2; ++i)
    {   //cout<<"======="<<endl;
        query_row(i, 1, 1, c, 0);//cout<<"======="<<endl;
        //cout << su<<endl;
        rtv_sum += su;
    }

    printf("%d %d %d\n",rtv_sum, mi, mx);
}

int main()
{

    while(scanf("%d%d%d",&r,&c,&m) != -1)
    {

        for(int i = 1; i <= r; ++i)
        {
            for(int j = 1; j <= m; j++)
            {
                set[i][j] = -1;add[i][j] = 0;
            }
            memset(mmin + i,0,sizeof(int) * (m + 1));
            memset(sum + i,0,sizeof(int) * (m + 1));
            memset(mmax + i,0,sizeof(int) * (m + 1));
           // for(int c = 1; c < m + 1; c++)cout << mmin[i][c] << endl;
        }

        while(m--)
        {
            scanf("%d%d%d%d%d",&t,&x1,&y1,&x2,&y2);

            if(t != 3)
            {
                scanf("%d",&v);
                updatas(x1,y1,x2,y2,v);
            }
            else if(t == 3)
            {
                query(x1,y1,x2,y2);
            }
        }
    }

    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值