UVA - 11992

题意:

那就N*M矩阵。三个操作1、X1 ,x2,y1,y2,k把左上角(x1,y1)到右下角(x2 y2)包起来的矩形所有元素+k. 第二个操作 还是输入五个 是把这区间元素全部置为k。第三个 输入左上右下坐标。输出这个矩形内最大元素 最小元素 和sum

tip:

第一眼看上去,如果是一维的,那么线段树就是够了的。但是二维,可以选择二维线段树,但是没写过233.
最开始被引导到分块,发现好像不太对QAQ,因为四周一圈都是要动的。
然后因为n*m是1e6的范围,就说明其中必有一个是小于1e3的,比如说是n,那么复杂度控制在n*logm*Q,Q是20000,就是说开了n个大小为m的线段树,这样比较方便写。。区间修改的时候,因为有置数的操作,那么在pushdown lazy标记的时候就比较麻烦,
首先关于update:当前区间是置数状态的时候,前面的add操作是没用的,如果在置数之后有对这个区间的add操作,那么add部分直接加到set上,就比如先置数为k再add m,那么直接置数k+m就好了,于是add只有再is_set为0,没有置数时才会被用到。
pushdown:这个时候先看是否置数了,
如果置数了,那么直接把两个儿子置数为改成这个值,然后自己的也清零,维护两个儿子最大最小和sum,(自己本身的再update时维护,因为pushdown是再不是整个区间的时候才走的,那么如果是整个区间,会直接return ,所以须在pushdown函数前维护好,就是update的时候直接维护了)。
如果没有置数,那么就是add了多少。这时候pushdown这个add要看,子区间是否处于set状态(wa了n小时),如果是set状态,那么这次的add还是要加在子区间的set上,如果子区间是add状态,直接加就好了,这个时候还是维护两个子区间的最大最小和sum就可以了,然后本区间置零。。。
关于开数组。。。vector,。。清零的时候要循环,不然只是清一维

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int N,M,Q,S1,S2,ty,x1,x2,y1,y2,v,S;
typedef pair<int , pair<int,int> > pii;
struct Tree{
    int maxvalue,minvalue,sum;
};
vector <vector<Tree> >dytree;
vector <vector<int> >_set,add,is_set;
void push_up(int i,int rt){
    dytree[i][rt].maxvalue = max(dytree[i][rt*2].maxvalue,dytree[i][rt*2+1].maxvalue);
    dytree[i][rt].minvalue = min(dytree[i][rt*2].minvalue,dytree[i][rt*2+1].minvalue);
    dytree[i][rt].sum = dytree[i][rt*2].sum+dytree[i][rt*2+1].sum;
}
void push_down(int i,int rt,int k){
    if(is_set[i][rt]){
        _set[i][rt*2] = _set[i][rt*2+1] = _set[i][rt];
        is_set[i][rt*2] = is_set[i][rt*2+1] = 1;
        add[i][rt] = add[i][rt*2] = add[i][rt*2+1] = 0;
        dytree[i][rt*2].maxvalue = dytree[i][rt*2].minvalue =  _set[i][rt];dytree[i][rt*2].sum = (k-(k>>1))*_set[i][rt];
        dytree[i][rt*2+1].maxvalue = dytree[i][rt*2+1].minvalue =  _set[i][rt];dytree[i][rt*2+1].sum = (k>>1)*_set[i][rt];
        is_set[i][rt] = _set[i][rt] = 0;
    }
    else if(add[i][rt]){
        int v = add[i][rt];
        if(is_set[i][rt*2]){
            _set[i][rt*2] += v;
            add[i][rt*2] = 0;
            dytree[i][rt*2].maxvalue = dytree[i][rt*2].minvalue = _set[i][rt*2];
            dytree[i][rt*2].sum = (k-(k>>1))*_set[i][rt*2];
        }
        else{
            add[i][rt*2] += v;
            dytree[i][rt*2].maxvalue += v;
            dytree[i][rt*2].minvalue += v;
            dytree[i][rt*2].sum += (k-(k>>1))*v;
        }
        if(is_set[i][rt*2+1]){
            _set[i][rt*2+1] += v;
            add[i][rt*2+1] = 0;
            dytree[i][rt*2+1].maxvalue = dytree[i][rt*2+1].minvalue = _set[i][rt*2+1];
            dytree[i][rt*2+1].sum = (k>>1)*_set[i][rt*2+1];
        }
        else{
            add[i][rt*2+1] += v;
            dytree[i][rt*2+1].maxvalue += v;
            dytree[i][rt*2+1].minvalue += v;
            dytree[i][rt*2+1].sum += (k>>1)*v;
        }
        add[i][rt] = 0;
    }
}
void update1(int i,int L,int R,int l,int r,int rt,int v){
    if(L <= l && r <= R){
        if(is_set[i][rt]){
            _set[i][rt] += v;
            add[i][rt] = 0;
            dytree[i][rt].maxvalue = dytree[i][rt].minvalue = _set[i][rt];
            dytree[i][rt].sum = (r-l+1)*_set[i][rt];
        }
        else{
            add[i][rt] += v;
            dytree[i][rt].maxvalue += v;
            dytree[i][rt].minvalue += v;
            dytree[i][rt].sum += (r-l+1)*v;
        }
        return;
    }
    push_down(i,rt,r-l+1);
    int m=(l+r)>>1;
    if(L <= m) update1(i,L,R,lson,v);
    if(R > m) update1(i,L,R,rson,v);
    push_up(i,rt);
}
void update2(int i,int L,int R,int l,int r,int rt,int v){
    if(L <= l && r <= R){
        _set[i][rt] = v;add[i][rt] = 0;is_set[i][rt] = 1;
        dytree[i][rt].maxvalue = dytree[i][rt].minvalue = v;
        dytree[i][rt].sum = (r-l+1)*v;
        return;
    }
    push_down(i,rt,r-l+1);
    int m=(l+r)>>1;
    if(L <= m) update2(i,L,R,lson,v);
    if(R > m) update2(i,L,R,rson,v);
    push_up(i,rt);
}

pii query(int i,int L,int R,int l,int r,int rt){
    if(l >= L && r <= R){
        return make_pair(dytree[i][rt].maxvalue,make_pair(dytree[i][rt].minvalue,dytree[i][rt].sum));
    }
    push_down(i,rt,r-l+1);
    int m=(l+r)>>1;
    pii tmp,t1,ans;
    t1.first = 0;t1.second.first = (1<<30) ; t1.second.second = 0;
    tmp.first = 0;tmp.second.first = (1<<30) ; tmp.second.second = 0;ans.first = 0;ans.second.first = (1<<30) ; ans.second.second = 0;
    if(L <= m)
        tmp = query(i,L,R,lson);
    if(R > m)
        t1 = query(i,L,R,rson);
    ans.first = max(tmp.first,t1.first);
    ans.second.first = min(tmp.second.first,t1.second.first);
    ans.second.second = tmp.second.second+t1.second.second;
    return ans;
}

void ty1(int x1,int y1,int x2,int y2,int v){
    //cout << "y1 = "<<y1<<"  y2 = "<<y2<<"  x1 = "<<x1 <<"  x2 = "<<x2 <<endl;
    for(int i = y1 ; i <= y2 ; i++){
        update1(i,x1,x2,1,N,1,v);
    }
}

void ty2(int x1,int y1,int x2,int y2,int v){
    for(int i = y1 ; i <= y2 ; i++){
        update2(i,x1,x2,1,N,1,v);
    }
}

void ty3(int x1,int y1,int x2,int y2){
    pii ans;
    ans.first = 0;ans.second.first = (1<<30) ; ans.second.second = 0;
    for(int i = y1 ; i <= y2 ; i++){
        pii tmp = query(i,x1,x2,1,N,1);
        //cout <<"check i : "<<i<<" max =  "<<tmp.first<<"   min - "<< tmp.second.first <<"  sun = "<<tmp.second.second<<endl;
        ans.first = max(ans.first,tmp.first);
        ans.second.first = min(tmp.second.first,ans.second.first);
        ans.second.second = tmp.second.second+ans.second.second;
    }
    printf("%d %d %d\n",ans.second.second,ans.second.first,ans.first);
}

void build(int i,int l,int r,int rt){
    dytree[i][rt].maxvalue = dytree[i][rt].minvalue = dytree[i][rt].sum = 0;
    if(l == r)    return;
    int m=(l+r)>>1;
    build(i,lson);
    build(i,rson);
}

void init(){
    S = 0;
    if (M > N){
        swap(N,M);
        S = 1;
    }
    S1 = M+10;S2 = 4*(N+10);

    dytree.resize(S1,vector<Tree>(S2));
    _set.resize(S1,vector<int>(S2));
    is_set.resize(S1,vector<int>(S2));
    add.resize(S1,vector<int>(S2));
    for(int i = 1 ; i <= M ; i++){
        build(i,1,N,1);
    }

    for(int i = 0 ; i <= M ; i++)
        for(int j = 0 ; j <=  4*N ; j++)
            _set[i][j] = add[i][j] = is_set[i][j]= 0;

}

void sov(){
    for(int i = 0 ;i < Q ; i++){
        scanf("%d",&ty);
        if(ty == 1){
            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&v);
            if(S){
                swap(x1,y1);
                swap(x2,y2);
            }
            ty1(x1,y1,x2,y2,v);
        }
        else if(ty == 2){
            scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&v);
            if(S){
                swap(x1,y1);
                swap(x2,y2);
            }
            ty2(x1,y1,x2,y2,v);
        }
        else if(ty == 3){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if(S){
                swap(x1,y1);
                swap(x2,y2);
            }
            ty3(x1,y1,x2,y2);
        }
//        if(i == 4)
//            cout <<": "<< dytree[2][2].minvalue << " "<<dytree[2][3].minvalue<<" "<<dytree[2][4].minvalue<<" "<<dytree[2][5].minvalue<<" "<<dytree[2][6].minvalue<<endl;
    }
}

int main(){
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    while(~scanf("%d%d%d",&N,&M,&Q)){
        init();
        sov();
    }
}
/*
15 17 12
2 4 6 14 8 54
1 7 4 13 11 46
1 8 10 14 15 67
1 2 3 13 10 21
3 2 10 14 15
2 7 7 15 11 32
1 6 2 14 14 59
2 9 7 15 14 71
2 5 8 11 12 92
2 5 8 14 15 59
2 6 1 13 4 64
3 6 1 14 10

15 17 4
1 4 6 14 8 54
1 6 2 14 14 59
1 9 7 15 14 71
3 6 1 14 10
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值