题意:

      给你一个矩阵,最大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. ArrayList源码分析笔记

    ArrayList源码分析笔记 先贴出ArrayList一些属性 public class ArrayList<E> extends AbstractList<E> imple ...

  2. Java8的新特性--函数式接口

    目录 函数式接口 什么是函数式接口 函数式接口的使用 Java8内置的四大核心函数式接口 一.Consumer:消费型接口(void accept(T t)) 二.Supplier:供给型接口(T g ...

  3. C#控制鼠标自动连续点(DEMO)

    ---------------------------界面---------------------------------------------------- ------------------ ...

  4. C++11多线程编程(常见面试题)

    [题目1] 子线程循环 10 次,接着主线程循环 100 次,接着又回到子线程循环 10 次,接着再回到主线程又循环 100 次,如此循环50次,试写出代码 [题解] 首先我们来分析一下这道题...( ...

  5. 总结下js排序算法和乱序算法

    其实本人最怕的就是算法,大学算法课就感觉老师在讲天书,而且对于前端来说,算法在实际的应用中实在是很有限.毕竟算法要依靠大量的数据为基础才能发挥出算法的效率,就浏览器那性能,......是吧,退一万步说 ...

  6. PureMVC学习笔记

    一.简介 PureMVC是基于MVC思想和一些基础设计模式建立的一个轻量级的应用框架,免费开源,最初是执行的ActionScript 3语言使用,现在已经移植到几乎所有主流平台.PureMVC官方网站 ...

  7. 自动统计zabbix过去一周监控告警

    # -*- coding:utf-8 -*-import jsonimport requestsimport time,datetimeimport csv,chardetdef getToken(u ...

  8. [源码解析] 分布式任务队列 Celery 之启动 Consumer

    [源码解析] 分布式任务队列 Celery 之启动 Consumer 目录 [源码解析] 分布式任务队列 Celery 之启动 Consumer 0x00 摘要 0x01 综述 1.1 kombu.c ...

  9. Spring Cloud Alibaba(1)---入门篇

    Spring Cloud Alibaba入门篇 有关微服务的一些概念的东西我这里就不再阐述了,因为之前在写Spring Cloud系列的时候都有详细写过. 具体地址: Spring Cloud系列博客 ...

  10. js 日期加减

    加: console.log(moment().format("YYYY-MM-DD HH:mm:ss")); //当前时间 console.log(moment().add(10 ...