(POJ 1151,HDU 1542,ZOJ 1128) Atlantis

素颜马尾好姑娘i 2022-06-17 04:11 292阅读 0赞

题目:

Time Limit: 2 Seconds Memory Limit: 65536 KB
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

Input

The input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0<=x1<⁢x2<=100000;0<=y1<⁢y2<=100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.

The input file is terminated by a line containing a single 0. Don��t process it1.
Output

For each test case, your program should output one section. The first line of each section must be ��Test case #k��, where k is the number of the test case (starting with 1). The second one must be ��Total explored area: a��, where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.

Output a blank line after each test case.

Sample Input

2
10 10 20 20
15 15 25 25.5
0

Sample Output

Test case #1
Total explored area: 180.00

题意:

求矩形的面积并

题解:

扫描线+线段树+离散化
Atlantis
把每个矩形投影到y坐标轴上来,然后我们可以枚举矩
形的 x 坐标,然后检测当前相邻x坐标上y方向的合法长度,两种相乘就是面积。
然后通过“扫描线”的方法来进行扫描,枚举 x 的竖边,矩形的左边那条竖
边就是入边,右边那条就是出边了。然后把所有这些竖边按照 x 坐标递增排序,每
次进行插入操作,由于坐标不一定为整数,因此需要进行离散化处理。每次插入时
如果当前区间被完全覆盖,那么就要对 cov 域进行更新。入边 +1 出边 -1,更新完
毕后判断当前节点的 cov 域是否大于 0 ,如果大于 0,那么当前节点的 len 域就是
节点所覆盖的区间。否则,如果是叶子节点,则 len=0。 如果内部节点,则 len=左
右儿子的 len 之和

代码:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <algorithm>
  5. #include <iomanip>
  6. using namespace std;
  7. const int maxn = 1000;
  8. double y[maxn];
  9. int n;
  10. struct Line
  11. {
  12. //把一段段平行于y轴的线段表示成数组 ,
  13. //x是线段的x坐标,y1,y2线段对应的下端点和上端点的坐标
  14. //一个矩形 ,左边的那条边f为1,右边的为-1,
  15. double x,y1,y2;
  16. int flag;
  17. bool operator < (const Line &line)
  18. {
  19. return x < line.x;
  20. }
  21. }line[maxn];
  22. struct node
  23. {
  24. int left;//线段树的左右整点
  25. int right;
  26. int cov;//c用来记录重叠情况
  27. double len,lf,rf;//len用来计算实在的长度,rf,lf分别是对应的左右真实的浮点数端点
  28. }node[maxn];
  29. void length(int t)//计算长度
  30. {
  31. if(node[t].cov > 0)
  32. {
  33. node[t].len = node[t].rf-node[t].lf;
  34. return;
  35. }
  36. if(node[t].left+1 == node[t].right)
  37. node[t].len = 0;
  38. else
  39. node[t].len = node[t<<1].len + node[t<<1|1].len;
  40. }
  41. void build(int t,int l,int r)
  42. {
  43. node[t].left = l;
  44. node[t].right = r;
  45. node[t].len = node[t].cov = 0;
  46. node[t].lf = y[l];
  47. node[t].rf = y[r];
  48. if(l+1==r)
  49. return;
  50. int mid = (l+r)>>1;
  51. build(t<<1,l,mid);
  52. build(t<<1|1,mid,r);
  53. }
  54. void update(int t,Line e)//加入线段e,后更新线段树
  55. {
  56. if(e.y1 == node[t].lf&&e.y2 == node[t].rf)
  57. {
  58. node[t].cov += e.flag;
  59. length(t);
  60. return;
  61. }
  62. if(e.y2<=node[t<<1].rf)
  63. update(t<<1,e);
  64. else if(e.y1>=node[t<<1|1].lf)
  65. update(t<<1|1,e);
  66. else
  67. {
  68. Line tmp = e;
  69. tmp.y2 = node[t<<1].rf;
  70. update(t<<1,tmp);
  71. tmp = e;
  72. tmp.y1 = node[t<<1|1].lf;
  73. update(t<<1|1,tmp);
  74. }
  75. length(t);
  76. }
  77. int main()
  78. {
  79. int Case = 0,t;
  80. double x1,y1,x2,y2;
  81. while(cin>>n&&n)
  82. {
  83. cout<<"Test case #"<<++Case<<endl;
  84. t = 1;
  85. for(int i=1;i<=n;i++)
  86. {
  87. cin>>x1>>y1>>x2>>y2;
  88. line[t].x = x1;
  89. line[t].y1 = y1;
  90. line[t].y2 = y2;
  91. line[t].flag = 1;
  92. y[t] = y1;
  93. t++;
  94. line[t].x = x2;
  95. line[t].y1 = y1;
  96. line[t].y2 = y2;
  97. line[t].flag = -1;
  98. y[t] = y2;
  99. t++;
  100. }
  101. sort(line+1,line+t);
  102. sort(y+1,y+t);
  103. build(1,1,t-1);
  104. update(1,line[1]);
  105. double ans = 0;
  106. for(int i=2;i<t;i++)
  107. {
  108. ans += node[1].len*(line[i].x - line[i-1].x);
  109. update(1,line[i]);
  110. }
  111. printf("Total explored area: %.2f\n\n",ans);
  112. }
  113. return 0;
  114. }

发表评论

表情:
评论列表 (有 0 条评论,292人围观)

还没有评论,来说两句吧...

相关阅读