HDU-1255 覆盖的面积(线段树扫描线模板+离散化+加点修改题)

「爱情、让人受尽委屈。」 2022-06-10 10:14 320阅读 0赞

给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

d1adc6253c233d9968f03fe1d872f86d_v_1502769328

Input

输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

注意:本题的输入数据较多,推荐使用scanf读入数据.

Output

对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.

Sample Input

  1. 2
  2. 5
  3. 1 1 4 2
  4. 1 3 3 7
  5. 2 1.5 5 4.5
  6. 3.5 1.25 7.5 4
  7. 6 3 10 7
  8. 3
  9. 0 0 1 1
  10. 1 0 2 1
  11. 2 0 3 1

Sample Output

  1. 7.63
  2. 0.00

题解:

一开始想套上我的扫描线模板的,但是因为模板写法与一般写法有些不同,所以又重新打了一遍,抱着会tle的心态把区间更新改成了单点更新,然后判断覆盖的改成了2次或以上,结果样例答案居然差0.01,再抱着侥幸的心态加上了一个玄学的eps(很小的数),答案居然对了。。。。。然后抱着一定会wa的心态交上去。。居然ac了,acm真是奇妙啊hhhhhh,后来分析了下可能是数据比较小就能这样怼出来,用的时间有点多是1500ms,不过距离题目的5s还差很远,没看题解a出来很开心,一会再想想更快的方法。

然后如果不懂扫描线操作看我之前的博客有讲解:http://blog.csdn.net/qq_37497322/article/details/75126251

ps:

刚刚写出了这题超快的写法,附上链接:http://blog.csdn.net/qq_37497322/article/details/77297203

代码:

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<stdio.h>
  5. #include<math.h>
  6. #include<string>
  7. #include<stdio.h>
  8. #include<queue>
  9. #include<stack>
  10. #include<map>
  11. #include<vector>
  12. #include<deque>
  13. using namespace std;
  14. #define lson k*2
  15. #define rson k*2+1
  16. #define M (t[k].l+t[k].r)/2
  17. #define INF 1008611111
  18. #define ll long long
  19. #define eps 1e-15//玄学
  20. struct node
  21. {
  22. int l,r;
  23. double len;
  24. int v;//覆盖次数
  25. }t[2005*4];
  26. double xx[2005];
  27. void Build(int l,int r,int k)
  28. {
  29. t[k].l=l;
  30. t[k].r=r;
  31. t[k].len=0.0;
  32. t[k].v=0;
  33. if(l==r)
  34. return;
  35. int mid=M;
  36. Build(l,mid,lson);
  37. Build(mid+1,r,rson);
  38. }
  39. void pushup(int k)//扫描线区间合并
  40. {
  41. if(t[k].v>1)
  42. {
  43. t[k].len=xx[t[k].r+1]-xx[t[k].l];
  44. }
  45. else
  46. {
  47. t[k].len=t[lson].len+t[rson].len;
  48. }
  49. }
  50. void update(int l,int r,int k,int d)//把扫描线模板的区间更新改成了区间下的单点更新
  51. {
  52. if(l<=t[k].l&&t[k].r<=r&&t[k].r==t[k].l)
  53. {
  54. t[k].v+=d;
  55. pushup(k);
  56. return;
  57. }
  58. int mid=M;
  59. if(l<=mid)
  60. update(l,r,lson,d);
  61. if(r>mid)
  62. update(l,r,rson,d);
  63. pushup(k);
  64. }
  65. struct edge
  66. {
  67. double l,r;
  68. double h;
  69. int d;
  70. }a[2005];
  71. int cmp(edge x,edge y)//按高度从小到大排序
  72. {
  73. if(x.h!=y.h)
  74. return x.h<y.h;
  75. return x.d<y.d;
  76. }
  77. int main()
  78. {
  79. int i,j,k,n,tot,l,r,test,ans;
  80. double x1,x2,y1,y2;
  81. scanf("%d",&test);
  82. while(test--)
  83. {
  84. scanf("%d",&n);
  85. tot=0;
  86. for(i=0;i<n;i++)
  87. {
  88. scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
  89. a[tot].l=x1;
  90. a[tot].r=x2;
  91. a[tot].h=y1;
  92. a[tot].d=1;
  93. a[tot+1].l=x1;
  94. a[tot+1].r=x2;
  95. a[tot+1].h=y2;
  96. a[tot+1].d=-1;
  97. xx[tot]=x1;
  98. xx[tot+1]=x2;
  99. tot+=2;
  100. }
  101. sort(xx,xx+tot);
  102. sort(a,a+tot,cmp);
  103. ans=unique(xx,xx+tot)-xx;//去重
  104. Build(0,ans-1,1);
  105. double s=0;
  106. for(i=0;i<tot;i++)
  107. {
  108. int l=lower_bound(xx,xx+ans,a[i].l)-xx;
  109. int r=lower_bound(xx,xx+ans,a[i].r)-xx-1;
  110. update(l,r,1,a[i].d);
  111. s+=(t[1].len*(a[i+1].h-a[i].h));
  112. }
  113. printf("%.2lf\n",s+eps);//玄学eps
  114. }
  115. return 0;
  116. }

发表评论

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

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

相关阅读