• UVa 11992 Fast Matrix Operations (线段树,区间修改)


    题意:给出一个row*col的全0矩阵,有三种操作
    1 x1 y1 x2 y2 v:将x1 <= row <= x2, y1 <= col <= y2里面的点全部增加v;

    2 x1 y1 x2 y2 v:将x1 <= row <= x2, y1 <= col <= y2里面的点全部变成v;

    3 x1 y1 x2 y2:输出x1 <= row <= x2, y1 <= col <= y2的点的和,最小值和最大值进行输出。

    析:一看题目,很容易看出来是线段树,可是。。。竟然要维护三个值,而且还有两种操作,增加或修改。。。。这日子没法过!!!一头雾水,懵逼中。。。

    一想这也太恐怖了吧,这怎么算,看着挺简单,做起来就恶心。本想都分开写,又觉得可能是会TLE,就只能凑合写了。。。写完后,一直崩,无法正常运行啊,原来是越界了,改完后又是bug多多啊,结果WA了好几次,查了好久,原来以为是数组开小了,后来加大也不对,差点就崩溃了,反复调整,终于过了,关键是我错了样例还一样过了。。。样例真是水,后台数据真是坑。。。

    分析一下这个题,矩阵虽然不超过20行,但是却有多达10的6次方个元素,可以建立一个一维线段树,把每行都拼起来。

    然后这个题有两个恶心的操作,set和add,所以我们就是做两个标记setv和addv,要不然一次更新都要改,时间会受不了,并且如果两个标记都存在进,先执行set再执行add,这个在pushdown中体现。

    注意两个update(updateadd和updateset)的递归边界,对于updateset操作要清除结点上的addv标记;但是对于updateadd操作则不清除setv标记,再就是不要越界,算好区间的端点。可以用位运算,简化一下代码。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    
    using namespace std;
    const int maxn = 1000005;
    const int INF = 0x3f3f3f3f;
    int sum[maxn<<2], minv[maxn<<2], maxv[maxn<<2], setv[maxn<<2], addv[maxn<<2];
    int minn, maxm;
    
    void pushup(int rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
        minv[rt] = min(minv[rt<<1], minv[rt<<1|1]);
        maxv[rt] = max(maxv[rt<<1], maxv[rt<<1|1]);
    }
    
    void pushdown(int rt, int len){
        int l = rt<<1, r = rt<<1|1;
        if(setv[rt] >= 0){//先考虑set
            addv[l] = addv[r] = 0;
            maxv[l] = maxv[r] = minv[l] = minv[r] = setv[rt];
            sum[l] = (len - (len>>1)) * setv[rt];
            sum[r] = (len>>1) * setv[rt];
            setv[l] = setv[r] = setv[rt];
            setv[rt] = -1;
        }
    
        if(addv[rt]){//再考虑add
            sum[l] += (len - len/2) * addv[rt];  sum[r] += (len/2) * addv[rt];
            minv[l] += addv[rt];  minv[r] += addv[rt];
            maxv[l] += addv[rt];  maxv[r] += addv[rt];
            addv[l] += addv[rt];  addv[r] += addv[rt];
            addv[rt] = 0;
        }
    }
    
    void build(int l, int r, int rt){//建树
        if(l == r){  sum[rt] = minv[rt] = maxv[rt] = 0;   return ; }
    
        int m = (l + r) >> 1;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void updateset(int L, int R, int val, int l, int r, int rt){//set操作
        if(L <= l && R >= r){
            sum[rt] = (r-l+1) * val;
            minv[rt] = maxv[rt] = val;
            addv[rt] = 0;//清除标记
            setv[rt] = val;
            return ;
        }
        pushdown(rt, r-l+1);
        int m = (l+r) >> 1;
        if(L <= m)  updateset(L, R, val, lson);
        if(R > m)  updateset(L, R, val, rson);
        pushup(rt);
    }
    
    void updateadd(int L, int R, int val, int l, int r, int rt){//add操作
        if(L <= l && R >= r){
            addv[rt] += val;
            sum[rt] += (r-l+1) * val;
            minv[rt] += val;  maxv[rt] += val;
            return ;//不清除标记
        }
    
        pushdown(rt, r-l+1);
        int m = (r+l) >> 1;
        if(L <= m)  updateadd(L, R, val, lson);
        if(R > m)  updateadd(L, R, val, rson);
        pushup(rt);
    }
    
    int query(int L, int R, int l, int r, int rt){
        if(L <= l && R >= r){
            minn = min(minn, minv[rt]);
            maxm = max(maxm, maxv[rt]);
            return sum[rt];
        }
    
        pushdown(rt, r-l+1);
        int m = (r+l) >> 1;
        int ans = 0;
        if(L <= m)  ans += query(L, R, lson);
        if(R > m)  ans += query(L, R, rson);
        return ans;
    }
    
    int main(){
    //    freopen("in.txt", "r", stdin);
        int r, c, q;
        while(~scanf("%d %d %d", &r, &c, &q)){
            memset(addv, 0, sizeof(addv));
            memset(setv, -1, sizeof(setv));
            memset(sum, 0, sizeof(sum));
            build(1, r*c, 1);
    
            int x1, x2, y1, y2, val, num;
            while(q--){
                scanf("%d %d %d %d %d", &num, &x1, &y1, &x2, &y2);
                --x1;  --x2;//注意不要越界,算好区间端点
                if(1 == num){
                    scanf("%d", &val);
                    for(int i = x1; i <= x2; ++i)
                        updateadd(i*c+y1, i*c+y2, val, 1, r*c, 1);
    //                puts("++");
                }
                else if(2 == num){
                    scanf("%d", &val);
                    for(int i = x1; i <= x2; ++i)
                        updateset(i*c+y1, i*c+y2, val, 1, r*c, 1);
                }
                else if(3 == num){
                    int ans = 0;
                    minn = INF,  maxm = -INF;//全局变量,初始化一下
                    for(int i = x1; i <= x2; ++i)
                        ans += query(i*c+y1, i*c+y2, 1, r*c, 1);
    
                    printf("%d %d %d
    ", ans, minn, maxm);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Python3和高性能全文检索引擎Redisearch进行交互
    Django项目连接多个数据库配置
    Redisearch实现的全文检索功能服务
    python一键搭建ftp服务
    yum提示错误: error: rpmdb: BDB0113 Thread/process 9866/140290246137664 failed:
    Django + FastDFS (分布式远程服务器存储文件)
    Docker来搭建分布式文件系统FastDfs
    VSCode---REST Client接口测试辅助工具
    在Centos下使用Siege对Django服务进行压力测试
    Mysql联合索引的最左前缀原则以及b+tree
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5528694.html
Copyright © 2020-2023  润新知