zoukankan      html  css  js  c++  java
  • UVA11992不错的线段树段更新

    题意:
          给你一个矩阵,最大20*50000的,然后有三个操作
    1 x1 y1 x2 y2 v  把子矩阵的值全部都加上v
    2 x1 y1 x2 y2 v  把子矩阵的值全部都变成v
    2 x1 y1 x2 y2  查询子矩阵的和,最大值,最小值


    思路:  
          首先我们观察,矩阵的行最多20行,那么我们就可以把每一行都建一颗线段树,这样就变成了一个一维的线段树段更新问题了,然后还有一个问题,就是操作1,和操作2,这两个操作放在一起感觉有些棘手,看白书上的思路不懂,没办法自己想了好久,想到了一个比较笨的思路,但感觉应该容易理解点,最近天天写软件,没怎么刷题,今天1a了感觉很开心啊,废话补多少回来说1,2的问题,我是这样想的,主要就是处理好延迟跟新的那个地方,总结就是一句话,在关系(延迟更新的是更改还是增加)传递的时候遇到“更改”那么下面的所有经过的点的属性都变成更改,其他情况直接由父节点传递过来,这么说可能不懂,我再换个角度说,对于某一个点,无论之前做过什么操作,如果现在是面临"更改"(不是增加)那么之前的操作全都无效,直接更改,如果面临的是增加操作,那么如果上一步是更改操作的话,那么从这一步起,之后就变成更改操作,具体细节可以看下面代码,自己想的思路可能不是很正宗,有点乱。
         




    #include<stdio.h>
    #include<string.h>


    #define R 20 + 2
    #define C 200000 + 100
    #define lson l ,mid ,t << 1
    #define rson mid + 1 ,r ,t << 1 | 1


    typedef struct
    {
        int sum ,min ,max;
    }NODE;


    int Sum[R][C] ,Max[R][C] ,Min[R][C];
    int mark[R][C] ,mks[R][C];
    int NOWI;


    int maxx(int x ,int y)
    {
        return x > y ? x : y;
    }


    int minn(int x ,int y)
    {
        return x < y ? x : y;
    }


    void Pushup(int t)
    {
        Sum[NOWI][t] = Sum[NOWI][t << 1] + Sum[NOWI][t << 1 | 1];
        Max[NOWI][t] = maxx(Max[NOWI][t << 1] ,Max[NOWI][t << 1 | 1]);
        Min[NOWI][t] = minn(Min[NOWI][t << 1] ,Min[NOWI][t << 1 | 1]);
        return ;
    }


    void Pushdown(int l ,int r ,int t)
    {
        if(mark[NOWI][t])
        {
            int ll = r - l + 1;
            if(mks[NOWI][t] == 1)
            {
                mark[NOWI][t<<1] = mark[NOWI][t<<1|1] = mark[NOWI][t];
                mks[NOWI][t<<1] = mks[NOWI][t<<1|1] = mks[NOWI][t];


                Sum[NOWI][t<<1] = (ll - ll / 2) * mark[NOWI][t];
                Sum[NOWI][t<<1|1] = (ll / 2) * mark[NOWI][t];


                Max[NOWI][t<<1] = Max[NOWI][t<<1|1] = mark[NOWI][t];
                Min[NOWI][t<<1] = Min[NOWI][t<<1|1] = mark[NOWI][t];


            }
            else
            {
                mark[NOWI][t<<1] += mark[NOWI][t];
                mark[NOWI][t<<1|1] += mark[NOWI][t];
                if(mks[NOWI][t<<1] != 1) mks[NOWI][t<<1] = 2;
                if(mks[NOWI][t<<1|1] != 1) mks[NOWI][t<<1|1] = 2;


                Sum[NOWI][t<<1] += (ll - ll / 2) * mark[NOWI][t];
                Sum[NOWI][t<<1|1] += (ll / 2) * mark[NOWI][t];


                Max[NOWI][t<<1] += mark[NOWI][t];
                Max[NOWI][t<<1|1] += mark[NOWI][t];


                Min[NOWI][t<<1] += mark[NOWI][t];
                Min[NOWI][t<<1|1] += mark[NOWI][t];


            }
            mark[NOWI][t] = mks[NOWI][t] = 0;
        }
    }


    void BuidTree()
    {
        memset(mark ,0 ,sizeof(mark));
        memset(mks ,0 ,sizeof(mks));
        memset(Sum ,0 ,sizeof(Sum));
        memset(Max ,0 ,sizeof(Max));
        memset(Min ,0 ,sizeof(Min));
    }


    void Update(int l ,int r ,int t ,int a ,int b ,int c ,int mk)
    {
        if(a <= l && b >= r)
        {
            if(mk == 1)
            {
                Sum[NOWI][t] = (r - l + 1) * c;
                Max[NOWI][t] = Min[NOWI][t] = c;
                mark[NOWI][t] = c;
                mks[NOWI][t] = 1;
            }
            else
            {
                Sum[NOWI][t] += (r - l + 1) * c;
                Max[NOWI][t] += c;
                Min[NOWI][t] += c;
                mark[NOWI][t] += c;
                if(mks[NOWI][t] != 1) mks[NOWI][t] = 2;
            }
            return;
        }
        Pushdown(l ,r ,t);
        int mid = (l + r) >> 1;
        if(a <= mid) Update(lson ,a ,b ,c ,mk);
        if(b > mid) Update(rson ,a ,b ,c ,mk);
        Pushup(t);
        return;
    }


    NODE Query(int l ,int r ,int t ,int a ,int b)
    {
        if(a <= l && b >= r)
        {
            NODE Ans;
            Ans.sum = Sum[NOWI][t];
            Ans.max = Max[NOWI][t];
            Ans.min = Min[NOWI][t];
            return Ans;
        }
        Pushdown(l ,r ,t);
        int tsum = 0 ,tmin = 1000000000 ,tmax = -1000000000;
        int mid = (l + r) >> 1;
        if(a <= mid)
        {
            NODE now = Query(lson ,a ,b);
            tsum += now.sum;
            if(tmin > now.min) tmin = now.min;
            if(tmax < now.max) tmax = now.max;
        }
        if(b > mid)
        {
            NODE now = Query(rson ,a ,b);
            tsum += now.sum;
            if(tmin > now.min) tmin = now.min;
            if(tmax < now.max) tmax = now.max;
        }
        NODE Ans;
        Ans.sum = tsum ,Ans.min = tmin ,Ans.max = tmax;
        return Ans;
    }


    int main ()
    {
        int x1 ,y1 ,x2 ,y2 ,key ,v ,r ,c ,m ,i;
        while(~scanf("%d %d %d" ,&r ,&c ,&m))
        {
            BuidTree();
            while(m--)
            {
                scanf("%d" ,&key);
                if(key == 1)
                {
                    scanf("%d %d %d %d %d" ,&x1 ,&y1 ,&x2 ,&y2 ,&v);
                    for(i = x1 ;i <= x2 ;i ++)
                    {
                        NOWI = i;
                        Update(1 ,c ,1 ,y1 ,y2 ,v ,2);
                    }
                }
                else if(key == 2)
                {
                    scanf("%d %d %d %d %d" ,&x1 ,&y1 ,&x2 ,&y2 ,&v);
                    for(i = x1 ;i <= x2 ;i ++)
                    {
                        NOWI = i;
                        Update(1 ,c ,1 ,y1 ,y2 ,v ,1);
                    }
                }
                else
                {
                   scanf("%d %d %d %d" ,&x1 ,&y1 ,&x2 ,&y2);
                   NODE Ans ,NOW;
                   for(i = x1 ;i <= x2 ;i ++)
                   {
                       NOWI = i;
                       NOW = Query(1 ,c ,1 ,y1 ,y2);
                       if(i == x1) Ans = NOW;
                       else
                       {
                           Ans.sum += NOW.sum;
                           Ans.max = maxx(Ans.max ,NOW.max);
                           Ans.min = minn(Ans.min ,NOW.min);
                       }
                   }
                   printf("%d %d %d " ,Ans.sum ,Ans.min ,Ans.max);
                }
            }
        }
    }


    /*
    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




    45 0 5
    78 5 7
    69 2 7
    39 2 7


    */







  • 相关阅读:
    C语言中static修饰符的意义
    网络字节序
    socket接口详解
    Python实现常见算法[3]——汉罗塔递归
    Python实现常见算法[2]——快速排序
    Python实现常见算法[1]——冒泡排序
    关于钛星设备主动推送报文的解析
    2015自我提升计划
    python 基础(函数 命名空间和作用域,嵌套和作用域链,闭包)
    python 基础(文件操作,注册,以及函数)
  • 原文地址:https://www.cnblogs.com/csnd/p/12062558.html
Copyright © 2011-2022 走看看