UVA11992 Fast Matrix Operations(线段树)

来源:互联网 发布:大风刮过知乎 编辑:程序博客网 时间:2024/05/19 18:12

题目链接:点击链接

题意:

  • 给一个矩阵,有三个操作。操作1,将这个矩阵的一个子矩阵的值全加上v。操作2,将这个矩阵的一个子矩阵的值全置为v。操作3,求这个矩阵的一个子矩阵的最大值,最小值,和。

思路:

  • 看似很简单的set和add操作,我这个线段树菜鸡,卡了很久。前几天写另一道线段树时,突然明白set操作和add操作先后顺序对答案的影响。

  • 都明白先add后set,前面的add会被置0,执行Set操作的时候,懒标记setv被置为v,懒标记addv被置为0。那么在push down的时候,会不会遇到setv和addv都不为0的情况?会的,这是先set后add的情况,此时两个标记都不为空,那么在push down操作里一定要先push down setv标记,把左儿子,右儿子的addv置0,再push down addv标记。所以push down函数里不能是if-else if的关系,而是if-if的关系。

  • 那这样的push down函数会不会对先add后set产生影响?不会,因为每次Set的时候,都把addv置0了。即先add后set,addv为0,setv为v,先set后add,addv和setv都不为0。

代码:

#include <iostream>#include <algorithm>#include <cstring>#include <cstdio>using namespace std;const int maxn = 1e6+100;long long _max, _min, _sum;class SegmentTree{public:    int minv[maxn<<2];    int maxv[maxn<<2];    int addv[maxn<<2];    int setv[maxn<<2];    int sumv[maxn<<2];    SegmentTree(){}    void build(){        memset(minv, 0, sizeof(minv));        memset(maxv, 0, sizeof(maxv));        memset(addv, 0, sizeof(addv));        memset(setv, 0, sizeof(setv));        memset(sumv, 0, sizeof(sumv));    }    void pushup(int rt){        minv[rt] = min(minv[rt<<1], minv[rt<<1|1]);        maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]);        sumv[rt] = sumv[rt<<1] + sumv[rt<<1|1];     }    void pushdown(int rt, int len){        if(setv[rt]!=0){            addv[rt<<1] = addv[rt<<1|1] = 0;            setv[rt<<1] = setv[rt<<1|1] = setv[rt];            minv[rt<<1] = minv[rt<<1|1] = setv[rt];            maxv[rt<<1] = maxv[rt<<1|1] = setv[rt];            sumv[rt<<1] = (len - len/2) * setv[rt];            sumv[rt<<1|1] = (len/2) * setv[rt];            setv[rt] = 0;        }        if(addv[rt]!=0){            addv[rt<<1] += addv[rt];            minv[rt<<1] += addv[rt];            maxv[rt<<1] += addv[rt];            sumv[rt<<1] += (len - len/2) * addv[rt];            addv[rt<<1|1] += addv[rt];            minv[rt<<1|1] += addv[rt];            maxv[rt<<1|1] += addv[rt];            sumv[rt<<1|1] += (len/2) * addv[rt];            addv[rt] = 0;        }    }    void Add(int rt, int a, int b, int l, int r,int x){        if(a<=l && r<=b){            sumv[rt] += (r-l+1) * x;            minv[rt] += x;            maxv[rt] += x;            addv[rt] += x;        }        else{            pushdown(rt, r-l+1);            int mid = (l+r)>>1;            if(a<=mid) Add(rt<<1, a, b, l, mid, x);            if(mid<b) Add(rt<<1|1, a, b, mid+1, r, x);            pushup(rt);        }    }    void Set(int rt, int a, int b, int l, int r, int x){        if(a<=l && r<=b){            sumv[rt] = (r-l+1) * x;            minv[rt] = x;            maxv[rt] = x;            addv[rt] = 0;            setv[rt] = x;        }        else{            pushdown(rt, r-l+1);            int mid = (l+r)>>1;            if(a<=mid) Set(rt<<1, a, b, l, mid, x);            if(mid<b) Set(rt<<1|1, a, b, mid+1, r, x);            pushup(rt);        }    }    void query(int rt, int a, int b, int l, int r){        if(a<=l && r<=b){            _sum += sumv[rt];            _min = min(_min, (long long)minv[rt]);            _max = max(_max, (long long)maxv[rt]);        }        else{            pushdown(rt, r-l+1);            int mid = (l+r)>>1;            if(a<=mid) query(rt<<1, a, b, l, mid);            if(mid<b) query(rt<<1|1, a, b, mid+1, r);            pushup(rt);        }    }}matrix[22];int main(){    int r, c, m, opt, x1, y1, x2, y2, v;    // freopen("in.txt", "r", stdin);    // freopen("out.txt", "w", stdout);    while(scanf("%d%d%d", &r, &c, &m)!=EOF){        for(int i=1; i<=r; ++i) matrix[i].build();        for(int j=0; j<m; ++j){            scanf("%d", &opt);            if(opt==1){                scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &v);                for(int i=x1; i<=x2; ++i){                    matrix[i].Add(1, y1, y2, 1, c, v);                }            }            if(opt==2){                scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &v);                for(int i=x1; i<=x2; ++i){                    matrix[i].Set(1, y1, y2, 1, c, v);                }            }            if(opt==3){                scanf("%d%d%d%d", &x1, &y1, &x2, &y2);                _sum = 0; _min = 0x3f3f3f3f; _max = -0x3f3f3f3f;                for(int i=x1; i<=x2; ++i){                    matrix[i].query(1, y1, y2, 1, c);                }                printf("%lld %lld %lld\n", _sum, _min, _max);            }        }    }    return 0;}
阅读全文
0 0
原创粉丝点击