【UVA11992】Fast Matrix Operations——二维线段树

给你 一个矩阵和一些的操作,计算子矩阵的和,最大值,最小值。1表示矩阵所有的元素加v,2表示矩阵所有的元素变为v,3表示查询区间的信息。由于最大只有20行,所以对于每一行建立一颗线段树。进行区间操作,比较恶心的是区间加和区间更改的关系。

#include <bits/stdc++.h>

using namespace std;

const int INF = 0x3f3f3f3f;
const int MAX = 41000;

struct node {

    int sum,maxn,minn;
    int op,lazy;
    int lson,rson;
    void Clear() {
        sum = 0; maxn = 0; minn = INF;
        op = lazy = 0;
    }
    node operator + (const node &a)const {
        node ans;
        ans.Clear();
        ans.sum = sum+a.sum;
        ans.minn = min(minn,a.minn);
        ans.maxn = max(maxn,a.maxn);
        return ans;
    }
}tr[42][MAX*5];

void pushup(int index,int st) {
    tr[index][st].sum = tr[index][st<<1].sum+tr[index][st<<1|1].sum;
    tr[index][st].minn = min(tr[index][st<<1].minn,tr[index][st<<1|1].minn);
    tr[index][st].maxn = max(tr[index][st<<1].maxn,tr[index][st<<1|1].maxn);
}

void pushdown1(node &a ,node &b) {
    b.sum +=(b.rson - b.lson+1)*a.lazy;
    b.maxn += a.lazy;
    b.minn += a.lazy;
    b.op = b.op == 2?2:1;
    b.lazy += a.lazy;
}
void pushdown2(node &a,node &b) {
    b.sum = (b.rson - b.lson +1)*a.lazy;
    b.maxn = b.minn = a.lazy;
    b.op = 2;
    b.lazy = a.lazy;
}
void pushdown(int index,int st) {//比较恶心的地方,向下lazy更新
    if(tr[index][st].lson == tr[index][st].rson || tr[index][st].op == 0) return ;
    if(tr[index][st].op == 1) {
        pushdown1(tr[index][st],tr[index][st<<1]);
        pushdown1(tr[index][st],tr[index][st<<1|1]);
    }
    else {
        pushdown2(tr[index][st],tr[index][st<<1]);
        pushdown2(tr[index][st],tr[index][st<<1|1]);
    }
    tr[index][st].lazy = tr[index][st].op = 0;
}

void Build(int index,int L,int R,int st) {
    tr[index][st].lson = L;
    tr[index][st].rson = R;
    tr[index][st].op = tr[index][st].lazy = 0;
    if(L == R) {
        tr[index][st].maxn = tr[index][st].sum = 0;
        tr[index][st].minn = 0;
        return ;
    }
    int mid = (L+R)>>1;
    Build(index,L,mid,st<<1);
    Build(index,mid+1,R,st<<1|1);
    pushup(index,st);
}

void Update(int index,int st,int l,int r,int val,int op) {//区间更新,找清两种操作之间的关系
    pushdown(index,st);
    if(l == tr[index][st].lson && r == tr[index][st].rson) {
        if(op == 1) {
            tr[index][st].sum += (r-l+1)*val;
            tr[index][st].minn += val;
            tr[index][st].maxn += val;
            tr[index][st].op = tr[index][st].op==2?2:1;
            tr[index][st].lazy += val;
        }
        else {
            tr[index][st].sum =  (r-l+1)*val;
            tr[index][st].maxn = tr[index][st].minn = val;
            tr[index][st].op = op;
            tr[index][st].lazy = val;
        }
        return ;
    }
    int mid = (tr[index][st].lson+tr[index][st].rson)>>1;
    if(r<=mid) Update(index,st<<1,l,r,val,op);
    else if(l>mid) Update(index,st<<1|1,l,r,val,op);
    else {
        Update(index,st<<1,l,mid,val,op);
        Update(index,st<<1|1,mid+1,r,val,op);
    }
    pushup(index,st);
}

node Query(int index,int st,int l,int r) {//查询操作
    pushdown(index,st);
    node ans; ans.Clear();
    if(l == tr[index][st].lson && tr[index][st].rson == r) return tr[index][st];
    int mid = (tr[index][st].lson + tr[index][st].rson ) >>1;
    if(r<=mid) ans = ans + Query(index,st<<1,l,r);
    else if(l>mid)  ans = ans + Query(index,st<<1|1,l,r);
    else {
        ans = ans + Query(index,st<<1,l,mid);
        ans = ans + Query(index,st<<1|1,mid+1,r);
    }
    pushup(index,st);//要及时的更新上去
    return ans;
}

int main() {
    int n,m,q,op,x1,y1,x2,y2,v;
    while(~scanf("%d %d %d",&n,&m,&q)) {
        for(int i = 1; i <= n; i++) Build(i,1,m,1);
        while(q--) {
            scanf("%d %d %d %d %d",&op,&x1,&y1,&x2,&y2);
            if(op!=3) {
                scanf("%d",&v);
                for(int i = x1;i<=x2;i++) Update(i,1,y1,y2,v,op);
            }
            else {
                node ans; ans.Clear();
                for(int i = x1;i<=x2;i++) ans =ans +  Query(i,1,y1,y2);
                printf("%d %d %d\n",ans.sum,ans.minn,ans.maxn);
            }
        }
    }
    return 0;
}
/*
input:
4 4 8
1 1 2 4 4 5
3 2 1 4 4
1 1 1 3 4 2
3 1 2 4 4
3 1 1 3 4
2 2 1 4 4 2
3 1 2 4 4
1 1 1 4 3 3
output:
45 0 5
78 5 7
69 2 7
39 2 7
*/

你可能感兴趣的:(【UVA11992】Fast Matrix Operations——二维线段树)