遇见poj上最浪漫的题目。。题目里图片以上几百词为一篇模板级英文情书。这情感和细腻的文笔深深地打动了我。。不会写情书的童鞋速度进来学习。传送门

题意:坐标系内有n个星星,每个星星都有一个亮度c (1<= c <= 100),坐标和亮度都已给出。 有一个矩形的窗户(就是个理想化的矩形),四条边与x轴或y轴平行。矩形可以在坐标系内平移,但不可以进行旋转操作。求这个矩形可以框住的星星的亮度之和最大为多少。注意:恰好在边上的星星不算在内。

思路:好吧,这题又是看别人的题解才做出来的,深深自责中。。。思路最主要也是最难想的地方就是,题目中是用矩形框住星星,在实际求解过程中要转化为对于每一颗星星,先找出能框住它的那些矩形(肯定不止一个)在坐标系内能够覆盖的区域。因为矩形可以平移,有无数中情况,但是极限情况就四种,就是星星位于矩形的四个顶点的情况。可以想象出,总区域该是四个矩形构成的一个大矩形。将这个矩形通过某种操作,覆盖上该星星的亮度c。最后的问题就转化为了,求坐标系内覆盖的亮度最大的矩形。这就转化到了用线段树扫描法求矩形面积的问题上了。

但实际解题过程中,只需要考虑星星位于矩形一个顶点时的情况(这里我也有些迷迷糊糊的,我的理解是,对于最后求得的结果,位于四个顶点的情况是等价的。可以想想最后得到的那个矩形里分布着不均匀的星星,可能对于某星星,这个矩形能够通过位于右上角顶点的情况计算出;对于另一个星星,可能就是右下角的情况了,所以从哪个顶点算都一样),这样处理起来也特别简单。

思路核心部分:题目中给出的矩形窗户的长为w,宽为h。现对于每一个星星(x, y),都想象一个以它为左下角顶点且长为w,宽为h的矩形。由于位于矩形边上的星星不算。因此这颗星星实际可以作用到的范围,x轴方向为[x, x+w),y轴方向为[y, y+h)。如果通过自下往上的扫描法,可以沿x轴建线段树,使用cover维护x轴区间内覆盖的亮度,使用tmax维护x轴区间内亮度的最大值。当扫描到一颗星星时,就将一条两端点分别为x, x+w-1(之所以减一,是因为线段树每个叶子表示的区间为该点到下一点之间的区间。),纵坐标为y,权值flag为该星星的亮度c的一条边覆盖到x轴上。但线继续朝上扫描时,当扫描到纵坐标为y+h时,该星星的亮度就不再起作用了。因此,对于每一颗星星,在坐标系内我们还要假象一条边,两端点为x, x+w-1,纵坐标为y+h,权值flag为-c。这样当扫描线到了y+h的高度时,将这条边覆盖到x轴上,便将之前的那条边给抵消了!

这样每往x轴上覆盖一条边,通过线段树维护数据,计算出当前x轴上存在的亮度和的最大值(可以肯定,一定存在一个长为w,宽为h的矩形,它框住的星星亮度和为此时计算出的亮度和最大值),若最大值大于ans,则赋值给ans。最后ans即为结果。

后话:因为x,y的坐标大小可达2^31,因此离散化是必须的。还有,x+w的范围可能超2^31,用int会wa,改成long long就ok了。

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #define maxn 22222
  5. #define lson l, m, rt << 1
  6. #define rson m + 1, r, rt << 1 | 1
  7. using namespace std;
  8. int cover[maxn<<], tmax[maxn<<];
  9. long long x[maxn];
  10. struct seg
  11. {
  12. long long l, r, h;
  13. int flag;
  14. seg() {}
  15. seg(long long x1,long long x2,long long y,int s) : l(x1), r(x2), h(y), flag(s) {}
  16. bool operator < (const seg &cmp) const
  17. {
  18. if (h == cmp.h) return flag < cmp.flag;
  19. return h < cmp.h;
  20. }
  21. }ss[maxn];
  22. int bin(long long key,int len,long long x[])
  23. {
  24. int l = , r = len - ;
  25. while (l <= r)
  26. {
  27. int m = (l + r) >> ;
  28. if (key == x[m]) return m;
  29. else if (key < x[m]) r = m - ;
  30. else l = m + ;
  31. }
  32. return -;
  33. }
  34. void PushDown(int rt)
  35. {
  36. if (cover[rt] != )
  37. {
  38. cover[rt<<] += cover[rt];
  39. cover[rt<<|] += cover[rt];
  40. tmax[rt<<] += cover[rt];
  41. tmax[rt<<|] += cover[rt];
  42. cover[rt] = ;
  43. }
  44. }
  45. void PushUp(int rt)
  46. {
  47. tmax[rt] = max(tmax[rt<<], tmax[rt<<|]);
  48. }
  49. void update(int L,int R,int c,int l,int r,int rt)
  50. {
  51. if (L <= l && r <= R)
  52. {
  53. cover[rt] += c;
  54. tmax[rt] += c;
  55. return;
  56. }
  57. PushDown(rt);
  58. int m = (l + r) >> ;
  59. if (L <= m) update(L, R, c, lson);
  60. if (m < R) update(L, R, c, rson);
  61. PushUp(rt);
  62. }
  63. int main()
  64. {
  65. int n, w, h;
  66. //freopen("data.in", "r", stdin);
  67. while (~scanf("%d%d%d",&n,&w,&h))
  68. {
  69. int tot = ;
  70. long long xi, y;
  71. int c;
  72. memset(cover, , sizeof(cover));
  73. memset(tmax, , sizeof(cover));
  74. for (int i = ; i < n; i++)
  75. {
  76. scanf("%lld%lld%d",&xi,&y,&c);
  77. x[tot] = xi;
  78. ss[tot++] = seg(xi, xi + w, y, c);
  79. x[tot] = xi + w;
  80. ss[tot++] = seg(xi, xi + w, y + h, -c);
  81. }
  82. sort(x, x + tot);
  83. sort(ss, ss + tot);
  84. int k = ;
  85. for (int i = ; i < tot; i++)
  86. if (x[i] != x[i-]) x[k++] = x[i];
  87. int ans = ;
  88. for (int i = ; i < tot - ; i++)
  89. {
  90. int l = bin(ss[i].l, k, x);
  91. int r = bin(ss[i].r, k, x) - ;
  92. if (l <= r) update(l, r, ss[i].flag, , k - , );
  93. if (ans < tmax[]) ans = tmax[];
  94. }
  95. printf("%d\n",ans);
  96. }
  97. return ;
  98. }

POJ 2482 Stars in Your Window 离散化+扫描法 线段树应用的更多相关文章

  1. POJ 2482 Stars in Your Window(扫描线+线段树)

    [题目链接] http://poj.org/problem?id=2482 [题目大意] 给出一些点的二维坐标和权值,求用一个长H,宽W的矩形能框住的最大权值之和, 在矩形边缘的点不计算在内 [题解] ...

  2. poj 2482 Stars in Your Window(扫描线)

    id=2482" target="_blank" style="">题目链接:poj 2482 Stars in Your Window 题目大 ...

  3. POJ 2482 Stars in Your Window(线段树)

    POJ 2482 Stars in Your Window 题目链接 题意:给定一些星星,每一个星星都有一个亮度.如今要用w * h的矩形去框星星,问最大能框的亮度是多少 思路:转化为扫描线的问题,每 ...

  4. poj 2482 Stars in Your Window + 51Nod1208(扫描线+离散化+线段树)

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13196   Accepted:  ...

  5. POJ 2482 Stars in Your Window 线段树扫描线

    Stars in Your Window   Description Fleeting time does not blur my memory of you. Can it really be 4 ...

  6. (中等) POJ 2482 Stars in Your Window,静态二叉树。

    Description Here comes the problem: Assume the sky is a flat plane. All the stars lie on it with a l ...

  7. POJ 2482 Stars in Your Window (线段树+扫描线+区间最值,思路太妙了)

    该题和 黑书 P102 采矿 类似 参考链接:http://blog.csdn.net/shiqi_614/article/details/7819232http://blog.csdn.net/ts ...

  8. POJ 2482 Stars in Your Window

    线段树+离散化+扫描线 AC之后,又认真读了一遍题目,好文章. #include<cstdio> #include<map> #include<algorithm> ...

  9. POJ 2482 Stars in Your Window 线段树

    如果按一般的思路来想,去求窗户能框住的星星,就很难想出来. 如果换一个思路,找出每颗星星能被哪些窗户框住,这题就变得非常简单了. 不妨以每个窗户的中心代表每个窗户,那么每颗星星所对应的窗户的范围即以其 ...

随机推荐

  1. Python import与from import使用

    Python程序可以调用一组基本的函数(即内建函数),比如print().input()和len()等函数.Python本身也内置一组模块(即标准库).每个模块都是一个Python程序,且包含了一组相 ...

  2. ADB push 和ADB pull命令

    adb push命令 :从电脑上传送文件到手机: adb pull命令 :从手机传送文件到电脑上      

  3. linux备忘录-档案与文件系统的压缩与打包

    知识点 文件扩展名与压缩解压缩工具 .Z -> compress程序压缩的档案 .gz -> gzip程序压缩的档案 .bz2 -> bzip2程序压缩的档案 .tar -> ...

  4. js万年历

    首先,注意: 1.延迟执行     window.setTimeout(    ,     )     里面的时间是以毫秒计算的 2.间隔执行    window.setInterval(     , ...

  5. oom 和 jvm crash的问题

    很多次生产环境jvm进程无故消失的时候都留下了hs_err[pid].log文件  然后通过mat分析大多数情况是oom导致的  所以以前一直认为OOM一定会导致jvm crash  也就是说java ...

  6. 【PHP】- 启用CRUL和GD

    1.修改php.ini文件,确保extension_dir配置为php目录的ext,如图: 2.修改php.ini文件,将以下两项取消注释: 3.将php目录下的 libeay32.dll 和 lib ...

  7. Nginx主要模块常用指令说明

    核心模块(Core Modules): 主模块(Main Module):配置和服务器全局有关的一些参数,比如错误日志.进程.权限等 user worker_processes error_logsy ...

  8. 【转】PHP对象在内存中的分配

    对像在PHP 里面和整型.浮点型一样,也是一种数据类,都是存储不同类型数据用的, 在运行的时候都要加载到内存中去用,那么对象在内存里面是怎么体现的呢?内存从逻辑上 说大体上是分为4 段,栈空间段.堆空 ...

  9. GCD 开发详情

    目录 一.简介 二.dispatch Queue - 队列 三.dispatch Groups - 组 四.dispatch Semaphores - 信号量 五.dispatch Barriers ...

  10. BZOJ - 2728 与非

    题意: 给定N个数,一个数k和一个范围[L,R].每个数可以使用任意次,k表示与非不超过k位.求出范围内有多少个数可以由他们的与非和表示. 题解: m个数进行NAND,最终的数二进制下某一位如果为1, ...