题意:

      给你一个矩阵,最大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\n" ,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

*/

UVA11992不错的线段树段更新的更多相关文章

  1. hdu4267线段树段更新,点查找,55棵线段树.

    题意:      给你N个数,q组操作,操作有两种,查询和改变,查询就是查询当前的这个数上有多少,更改是给你a b k c,每次从a到b,每隔k的数更改一次,之间的数不更改,就相当于跳着更新. 思路: ...

  2. hdu4046 不错的线段树单点更新

    题意:       给一个字符串,两种操作 0 a b 询问a,b之间有多少个wbw, 1 a c 就是把第a个改成c. 思路:       这个题目我们可以用线段树的点更新来做,一开始写了个好长好长 ...

  3. hdu1556 线段树段更新(简单题)

    题意: N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的"小飞鸽"牌电动车从气球a开始到气球b依次给每个 ...

  4. POJ2528线段树段更新逆序异或(广告牌)

    题意:      可以这样理解,有一条直线,然后用n条线段去覆盖,最后问全部都覆盖完之后还有多少是没有被完全覆盖的. 思路:      一开始想的有点偏,想到起点排序,然后..失败了,原因是忘记了题目 ...

  5. POJ3277 线段树段更新,点询问+二分离散化+暴力

    题意:       x轴上有一些矩形,问你这些矩形覆盖的面积和是多少. 思路:       首先范围很大,n很小,果断离散化,然后我们就是求出任意区间的最大值作为当前区间的高,最后在算一遍答案就行了, ...

  6. ZOJ 1610 Count the Colors (线段树区间更新)

    题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头 ...

  7. zoj 1610 Count the Colors(线段树延迟更新)

    所谓的懒操作模板题. 学好acm,英语很重要.做题的时候看不明白题目的意思,我还拉着队友一块儿帮忙分析题意.最后确定了是线段树延迟更新果题.我就欣欣然上手敲了出来. 然后是漫长的段错误.... 第一次 ...

  8. HDU 1166 敌兵布阵(线段树单点更新,板子题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  9. UESTC 1591 An easy problem A【线段树点更新裸题】

    An easy problem A Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others ...

随机推荐

  1. C#的foreach遍历循环和隐式类型变量

    C#的foreach遍历循环和隐式类型变量 foreach遍历循环 foreach (<baseType> <name> in <array>>) { //c ...

  2. C#类中的字段、属性和方法

    C#类中的字段.属性和方法 刚开始学C#,对于类中的字段.属性和方法很难分清,写下这份笔记,帮助理解 字段:与类相关的变量 声明方法与声明变量类似,可在前面添加访问修饰符.static关键字等: 属性 ...

  3. 致被职场PUA的打工人

    作为打工人,除了每天面对着各种繁琐的工作,还要被动接受上级或多或少的PUA,实在是难上加难,甚至有人想不开而自杀.网络上最近流行了一个词:职场PUA,赋予了这种现象一个正式的名字. 职场PUA指的是职 ...

  4. 使用egg.js开发后端API接口系统

    什么是Egg.js Egg.js 为企业级框架和应用而生,我们希望由 Egg.js 孕育出更多上层框架,帮助开发团队和开发人员降低开发和维护成本.详细的了解可以参考Egg.js的官网:https:// ...

  5. ts装饰器的用法,基于express创建Controller等装饰器

    TS TypeScript 是一种由微软开发的自由和开源的编程语言.它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类 型和基于类的面向对象编程. TypeScript 扩 ...

  6. Intellij IDEA maven设置tomcat

    1 pom.xml配置插件 <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId&g ...

  7. ES6学习笔记(3)- 对象的功能性扩展

    一.什么是对象字面量 对象字面量就是创建对象(Object)的一种简单容易理解的方式,再通俗点就是所谓的键值对的集合.举个简单的例子: let book = { name: 'JavaScript', ...

  8. go调用python命令行参数过量报错python.exe: The filename or extension is too long.的解决方法

    当我们在调用python时,如果传入的参数数据量过大时会报错 python.exe: The filename or extension is too long. 这时候我们的解决办法是放弃传参,将想 ...

  9. 使用 DD 命令制作 USB 启动盘

    Windows 下有很多很好用的 USB 启动盘制作工具,比如 Rufus,但是 MacOS 下这个类型的工具就少了很多,这里记录下在 MacOS 中用 DD 命令制作 Linux USB 启动盘的操 ...

  10. Just a Joke HDU - 4969(物理+积分)

    题目链接:https://vjudge.net/problem/HDU-4969#author=0 题意:一个人在圆心以V2速度追赶一个以V1的速度进行圆周运动,问在圆心的人能否在不超过D的距离追上他 ...