题意:
      给你一个矩阵,最大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. hdu4046 不错的线段树单点更新

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

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

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

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

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

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

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

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

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

  6. HDUOJ----1166敌兵布阵(线段树单点更新)

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

  7. hdu 3954(线段树区间更新)

    转载标记处:http://www.cnblogs.com/wang-jue/articles/2920341.html 思路:这道题所得到的经验与每个英雄的等级有关,一般的可能就用线段树一直更新到每一 ...

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

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

  9. POJ 2777 ZOJ 1610 HDU 1698 --线段树--区间更新

    直接将这3题 放一起了  今天在做线段树的东西 这3个都是区间更新的 查询方式互相不同 反正都可以放到一起吧 直接先上链接了 touch me touch me touch me 关于涉及到区间的修改 ...

最新文章

  1. erlang精要(18)-以函数作为参数的函数,返回函数的函数(1)
  2. mysql分片库分页查询_mysql数据库分页查询优化
  3. mysql 出现错误 Duplicate entry for key PRIMARY 解决办法
  4. usaco-sprime-superprime-pass
  5. 【logstash】logstash monitor
  6. 三星s8android pie,三星确认了Galaxy S8/S8+及Note9等手机的Android
  7. iOS开发之通过代理逆向传值
  8. win7修复音频服务器,win7系统下realtek高清晰音频管理器没有声音怎么修复
  9. Pascal 转 C++ 教程2
  10. C语言 数组插入 – 插入排序
  11. Win10 快速检查修复系统方法
  12. 移动终端安全问题分析与解决方案研究
  13. C# 基础(三十一)c#实现 正弦sin、反正弦arcsin,正切tan、反正切arctan:求角度值
  14. AnyPi智能语音音箱方案 智能蓝牙WIFI音箱方案开发 DuerOS及Alexa平台
  15. C语言:在文件的指定位置实现局部修改,而无需重写文件的其他部分
  16. 第三代战斗机的特点有哪些
  17. 如何写论文中的引言?
  18. springBoot 双数据源配置 (Oracle+ SQL sever)主数据源配置setMapperLocations多个路径
  19. 2.ZooKeeper分桶策略实现高性能的会话管理「第五章 ZooKeeper 原理」「架构之路ZooKeeper理论和实战」
  20. 音频格式转换器哪个好?建议收藏这两个转换器

热门文章

  1. GitHub https链接中输入账户和密码
  2. 通过组策略实现IE自动以当前域账号登录某站点
  3. git使用,Git的skil-map
  4. 翟树卿:如何让数据挖掘助力精准化营销
  5. 启动nuxt项目fsevents报错
  6. Hexo搭建个人网站
  7. Solr字段类型field type的定义
  8. windows根据端口号找进程
  9. 绑定变量窥测(Bind Variable Peeking)
  10. HokeyPokey — WWDC讲师特供XCode插件高仿版的设计与实现