区间更新与单点更新最大的不同就在于Lazy思想:

http://blog.sina.com.cn/s/blog_a2dce6b30101l8bi.html

可以看这篇文章,讲得比较清楚

在具体使用上,因为是成段更新,目标区间内所有区间都需要更新,所以update时可以专门去找区间,不用一个个找点。所以可以不用node保存每个点左右范围,用a[]保存值,col[]保存标记反而比较方便

区间替换和区间增减在我的http://www.cnblogs.com/qlky/p/5690265.html中都写了,这里讲一下离散化:

离散化就是有时n个点的数据范围过大,或者过于分散。我们将节点映射到1-n中可以简化问题。基本过程如下:

  • 记录每个点的左端和右端,全部保存到一个数组a中并排序
  • 节点去重
  • 如果两个节点间距离大于1,添加一个中间节点
  • 再次对a排序
  • 在a中二分搜索原来每个点的左右端,将索引值保存在线段树中

示例代码:

sf("%d",&n);int cnt = 0,len = 1;for(i=1;i<=n;i++)//记录头尾
        {sf("%d %d",&s1[i],&s2[i]);a[++cnt] = s1[i];a[++cnt] = s2[i];}sort(a+1,a+1+cnt);for(i=2;i<=cnt;i++)//去重
        {if(a[i]!=a[i-1]) a[++len] = a[i];}for(i=len;i>1;i--)//添加中间值
        {if(a[i]-a[i-1]>1) a[++len] = a[i]-1;}sort(a+1,a+1+len);for(i=1;i<=n;i++){int l = BSearch(1,len,s1[i]);int r = BSearch(1,len,s2[i]);update(i,l,r,1,len,1);}

以poj 2528为例:

http://blog.csdn.net/non_cease/article/details/7383736

题意:n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000)。

求出最后还能看见多少张海报。

输入:

1
5
1 4
2 6
8 10
3 4
7 10

解法:离散化,如下面的例子(题目的样例),因为单位1是一个单位长度,将下面的

1   2   3   4  6   7   8   10

—  —  —  —  —  —  —  —

1   2   3   4  5   6   7   8

离散化  X[1] = 1; X[2] = 2; X[3] = 3; X[4] = 4; X[5] = 6; X[7] = 8; X[8] = 10

于是将一个很大的区间映射到一个较小的区间之中了,然后再对每一张海报依次更新在宽度为1~8的墙上(用线段树),最后统计不同颜色的段数。

但是只是这样简单的离散化是错误的,

如三张海报为:1~10 1~4 6~10

离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。

新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)

X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10

这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3

最终,1~2为2,3为1,4~5为3,于是输出正确结果3。

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <cctype>
#include <vector>
#include <iterator>
#include <set>
#include <map>
#include <sstream>
using namespace std;#define mem(a,b) memset(a,b,sizeof(a))
#define pf printf
#define sf scanf
#define spf sprintf
#define pb push_back
#define debug printf("!\n")
#define MAXN 10000 + 5
#define MAX(a,b) a>b?a:b
#define blank pf("\n")
#define LL long long
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pqueue priority_queue
#define INF 0x3f3f3f3fint n,m;int a[MAXN<<4],col[MAXN<<4],ans;int s1[MAXN],s2[MAXN];bool hh[MAXN];void PushDown(int rt)
{if(col[rt] != -1){col[rt<<1] = col[rt<<1|1] = col[rt];col[rt] = -1;}
}void update(int val,int L,int R,int l,int r,int rt)
{if(L <= l && r <= R){col[rt] = val;return;}PushDown(rt);int mid = (l + r)>>1;if (L <= mid){update(val,L,R,l,mid,rt<<1);}if(R > mid){update(val,L,R,mid+1,r,rt<<1|1);}
}void query(int l,int r,int rt)
{if(l==r){if(!hh[col[rt]]){ans++;hh[col[rt]] = true;}return;}PushDown(rt);int mid = (l + r)>>1;query(l,mid,rt<<1);query(mid+1,r,rt<<1|1);
}int BSearch(int lo, int hi, int v)
{int mid;while (lo <= hi){mid = (lo + hi) >> 1;if (a[mid] == v) return mid;else if (a[mid] > v)  hi = mid - 1;else lo = mid + 1;}return -1;
}int main()
{int t,i,kase=1;sf("%d",&t);while(t--){mem(col,-1);mem(a,0);mem(hh,false);sf("%d",&n);int cnt = 0,len = 1;for(i=1;i<=n;i++)//????
        {sf("%d %d",&s1[i],&s2[i]);a[++cnt] = s1[i];a[++cnt] = s2[i];}sort(a+1,a+1+cnt);for(i=2;i<=cnt;i++)//??
        {if(a[i]!=a[i-1]) a[++len] = a[i];}for(i=len;i>1;i--)//?????
        {if(a[i]-a[i-1]>1) a[++len] = a[i]-1;}sort(a+1,a+1+len);for(i=1;i<=n;i++){int l = BSearch(1,len,s1[i]);int r = BSearch(1,len,s2[i]);update(i,l,r,1,len,1);}ans = 0;query(1,len,1);pf("%d\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/qlky/p/5716796.html

ACM-线段树区间更新+离散化相关推荐

  1. hdu 5692 Snacks(dfs序+线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5692 解题思路:这道题是树节点的点权更新,而且涉及到子树,常用的思路是利用dfs序,用线段树来对区间进 ...

  2. Just a Hook(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 In the game of DotA, Pudge's meat hook is actual ...

  3. hdu 1698(线段树区间更新)

    解题思路:线段树区间更新水题. #include<iostream> #include<cstdio> #include<cstring> using namesp ...

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

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

  5. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

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

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

  7. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,"模拟都市"是他们非常喜欢的一个游戏 ...

  8. CodeForces - 272C Dima and Staircase (线段树区间更新)

    题意: 见以下样例,给出 5 个区间,每个区间的高度已知.一共 4 次操作.每次操作都是从最左边开始向下垒一个宽为 w 高为h 的木块,过程见下图. 问每次垒木块的高度是多少? Input 5 1 2 ...

  9. CDOJ-1057 秋实大哥与花(线段树区间更新)

    秋实大哥与花 Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Submit St ...

  10. Codeforces 444C DZY Loves Colors 线段树区间更新

    // Codeforces 444C DZY Loves Colors 线段树区间更新// 题目链接:// http://codeforces.com/problemset/problem/444/C ...

最新文章

  1. mysql duplicate jpa_SpringBoot Jpa 双数据源mysql + oracle + liquibase+参考源码
  2. 像@Transactional一样利用注解自定义aop切片
  3. Microsoft SQL Server 存储过程
  4. 批量替换文件夹下所有文件的内容
  5. django-xadmin使用之更改菜单url
  6. php 获取子孙,jquery如何查找后代元素?jquery获取后代元素方法
  7. java上机实验答案_java上机实验答案与解析
  8. R语言列表(list)与向量(numeric)的转换
  9. C++标识符的命名规则
  10. 130号:SpringBoot使用AOP
  11. php 计算签名,php – 计算Amazon Marketplace API的签名问题
  12. 天翼网关获取超级密码
  13. 使用wxPython内嵌浏览器
  14. Ra-08系列开发板入门教程,标准LoRaWAN对接私有服务器。
  15. 关于微信旧版本扫码登陆,旧版的登陆限制的一些经验
  16. iphone手机屏幕投射电脑 简单几步教你完成
  17. 文件夹病毒或1K病毒解决
  18. Python海龟绘图入门篇
  19. 【办公Tips】 如何快速将一列Excel值变成一段用符号间隔的文字
  20. Oracle误删除数据的恢复方法(转)

热门文章

  1. 520晚上,我用python破解了前女友的加密文件,结果却发现。。。
  2. matlab将txt数据分类,MATLAB读取txt文件,txt里面有字符串和数值两种类型
  3. Nodejs版本的企业微信中接收消息与腾讯对接之验证URL 代码已经上传,可以去下载
  4. c语言如何写地图,自己用C语言写的扫雷地图
  5. python获取当前日期的前一天爆炸_python蒙特卡洛脚本模拟—挑战者号爆炸概率
  6. 删除华为电视鸿蒙系统,华为解决互联网电视痛点:鸿蒙系统首发设备欲屏蔽开机广告...
  7. sweetalert2不相应回车_你还不知道的SketchUp建模小技能
  8. java线程池_Java 线程池 8 大拒绝策略,面试必问!
  9. 基于AUTOSAR的AP平台的应用开发
  10. Chess DP 思维题