题目网址:http://poj.org/problem?id=2528

题意:

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

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

  输入:

  1.  1
  2.  5
  3.  1 4
  4.  2 6
  5.  8 10
  6.  3 4
  7.  7 10
     这题用常规思路解题必定TLE,l,r太大;

通俗点说,离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:

有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。

现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9

然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9

对其升序排序,得2 3 4 6 8 9 10

然后建立映射

2     3     4     6     8     9   10

↓     ↓      ↓     ↓     ↓     ↓     ↓

1     2     3     4     5     6     7

那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。

离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include <algorithm>
  4. #include <string.h>
  5. using namespace std;
  6. #define N 10100
  7. #define M 10000000
  8. bool vis[*N];//标记出现过得海报
  9. int x[*N];
  10. struct T
  11. {
  12. int node,add,l,r;
  13. }tree[M*];
  14. void creat(int l,int r,int k)//建树
  15. {
  16. tree[k].node=;
  17. tree[k].l=l;
  18. tree[k].r=r;
  19. tree[k].add=;
  20. if(l==r)
  21. return;
  22. int mid=(l+r)>>;
  23. creat(l,mid,k<<);
  24. creat(mid+,r,k<<|);
  25. }
  26. void pushdown(int k,int color)//延迟标记
  27. {
  28. int x=k<<;
  29. tree[x].add=;
  30. tree[x+].add=;
  31. tree[x].node=color;
  32. tree[x+].node=color;
  33. tree[k].add=;
  34. tree[k].node=;
  35. }
  36. void Search(int l,int r,int color,int k)//更新线段树
  37. {
  38. if(r<tree[k].l||l>tree[k].r)
  39. return ;
  40. if(l<=tree[k].l&&r>=tree[k].r)
  41. {
  42. tree[k].node=color;
  43. tree[k].add=;
  44. return ;
  45. }
  46. if(tree[k].add)
  47. pushdown(k,tree[k].node);
  48. int mid=(tree[k].l+tree[k].r)>>;
  49. if(r<=mid)
  50. Search(l,r,color,k<<);
  51. else if(l>mid)
  52. Search(l,r,color,k<<|);
  53. else
  54. {
  55. Search(l,mid,color,k<<);
  56. Search(mid+,r,color,k<<|);
  57. }
  58. }
  59. int ans;
  60. void q(int l,int r,int k)//查找不同颜色的区域
  61. {
  62. if(tree[k].add)
  63. {
  64. if(!vis[tree[k].node])
  65. {
  66. ans++;
  67. vis[tree[k].node]=;
  68. }
  69. return ;
  70. }
  71. int mid=(l+r)>>;
  72. q(l,mid,k<<);
  73. q(mid+,r,k<<|);
  74. }
  75. int s(int l,int r,int k)//二分查找
  76. {
  77. int mid;
  78. while(l<=r)
  79. {
  80. mid=(l+r)>>;
  81. if(k<x[mid]) r=mid-;
  82. else if(k>x[mid]) l=mid+;
  83. else return mid;
  84. }
  85. return -;
  86. }
  87. int main()
  88. {
  89. int t,n,i,j;
  90. int l[N],r[N];
  91. scanf("%d",&t);
  92. while(t--)
  93. {
  94. j=;
  95. memset(vis,,sizeof(vis));
  96. scanf("%d",&n);
  97. for(i=;i<n;i++)
  98. {
  99. scanf("%d%d",&l[i],&r[i]);
  100. x[j++]=l[i];
  101. x[j++]=r[i];
  102. }
  103. sort(x,x+j);
  104. int m=;
  105. for(i=;i<j-;i++)
  106. {
  107. if(x[i]==x[i+])
  108. {
  109. m--;
  110. }
  111. else
  112. {
  113. x[i+m]=x[i+];
  114. }
  115. }
  116. j=j+m-;
  117. sort (x,x+j);
  118. /*for(i=0;i<n;i++)
  119. {
  120. printf("%d %d ",s(0,j-1,l[i])+1,s(0,j-1,r[i])+1);
  121. cout<<endl;
  122. }*/
  123. creat(,j,);
  124. for(i=;i<n;i++)
  125. {
  126. Search(s(,j-,l[i])+,s(,j-,r[i])+,i+,);
  127. }
  128. ans=;
  129. q(,j,);
  130. printf("%d\n",ans);
  131. }
  132. return ;
  133. }

poj2528线段树解题报告,离散化+线段树的更多相关文章

  1. 【九度OJ】题目1172:哈夫曼树 解题报告

    [九度OJ]题目1172:哈夫曼树 解题报告 标签(空格分隔): 九度OJ http://ac.jobdu.com/problem.php?pid=1172 题目描述: 哈夫曼树,第一行输入一个数n, ...

  2. [POJ2528]Mayor's posters(离散化+线段树)

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 70365   Accepted: 20306 ...

  3. hdu 1754 I Hate It 解题报告(线段树 代码+注释)

    题目链接:传送门 I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  4. 洛谷 P3924 康娜的线段树 解题报告

    P3924 康娜的线段树 题目描述 小林是个程序媛,不可避免地康娜对这种人类的"魔法"产生了浓厚的兴趣,于是小林开始教她\(OI\). 今天康娜学习了一种叫做线段树的神奇魔法,这种 ...

  5. [jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)

    题目链接: https://jzoj.net/senior/#main/show/6086 题目: 题解: 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘 这样的子树 ...

  6. 「ZJOI2019」线段树 解题报告

    「ZJOI2019」线段树 听说有人喷这个题简单,然后我就跑去做,然后自闭感++,rp++(雾) 理性分析一波,可以发现最后形成的\(2^k\)个线段树,对应的操作的一个子集,按时间顺序作用到这颗线段 ...

  7. OrzFAng系列–树 解题报告

    题目描述 方方方种下了三棵树,两年后,第二棵树长出了n个节点,其中1号节点是根节点. 给定一个n个点的树 支持两种操作 方方方进行m次操作,每个操作为: (1)给出两个数i,x,将第i个节点的子树中, ...

  8. [BZOJ1984]月下“毛景树”解题报告|树链剖分

    Description 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里.爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树” ...

  9. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

随机推荐

  1. MySQL的order by子句

    1.语法:select 字段列表 from 表名 [where 子句][group by 子句][having 子句][order by 子句]; 注解: 1.默认是从第一条记录开始升序, 2.des ...

  2. poj2420(模拟退火大法好)

    // // main.cpp // poj2420 // // Created by 陈加寿 on 16/2/13. // Copyright © 2016年 chenhuan001. All rig ...

  3. 【BZOJ4716】假摔 二分+暴力

    [BZOJ4716]假摔 Description [题目背景] 小Q最近喜欢上了一款游戏,名为<舰队connection>,在游戏中,小Q指挥强大的舰队南征北战,从而成为了一名dalao. ...

  4. 迷宫问题(java实现)

    1. public class Direction { private int x; private int y; public Direction(int x, int y) { this.x = ...

  5. 时间格式化输出strtime

    The format argument consists of one or more codes; as in printf, the formatting codes are preceded b ...

  6. "大中台、小前台”新架构下,阿里大数据接下来怎么玩? (2016-01-05 11:39:50)

    "大中台.小前台”新架构下,阿里大数据接下来怎么玩?_炬鼎力_新浪博客 http://blog.sina.com.cn/s/blog_1427354e00102vzyq.html " ...

  7. 用户画像 销量预测 微观 宏观 bi

    w 目前我们没有自己的平台 第三方平台又不会给任何我们想要的数据   没有用户的注册信息 全天候的行为信息   用户画像没法做    针对我们业务的bi做的思路是什么呢   数据中心怎么做销量预测呢 ...

  8. STL中的二分查找——lower_bound 、upper_bound 、binary_search

    STL中的二分查找函数 1.lower_bound函数 在一个非递减序列的前闭后开区间[first,last)中.进行二分查找查找某一元素val.函数lower_bound()返回大于或等于val的第 ...

  9. selenium 下载文件设置下载路径

    Chrome 文件下载 Chrome浏览器类似,设置其options: download.default_directory:设置下载路径 profile.default_content_settin ...

  10. nodejs的精简型和全栈型开发框架介绍

    总体来说你可以将Node.js开发框架归结为两类: - 精简型框架 - 全栈型框架 下面我们就对这两种框架进行探讨. 精简型框架 精简型框架提供的是最基本的功能和APIs,这类框架本身就是被设计成用来 ...