HDU 1255 覆盖的面积 ——(线段树+扫描线)

  又做了一题扫描线以后对节点的覆盖标记理解的更加深刻了。

  代码如下:

  1 #include <stdio.h>
  2 #include <algorithm>
  3 #include <string.h>
  4 #define t_mid (l+r>>1)
  5 #define ls (o<<1)
  6 #define rs (o<<1|1)
  7 #define lson ls,l,t_mid
  8 #define rson rs,t_mid+1,r
  9 using namespace std;
 10 const int N = 1000 + 5;
 11 const int MAX = N * 2;
 12 const double eps = 1e-6;
 13
 14 struct seg
 15 {
 16     double x1,x2,y;
 17     int d;
 18     bool operator < (const seg & temp) const
 19     {
 20         return std::fabs(y-temp.y) <= eps ? d > temp.d : y < temp.y;
 21     }
 22 }g[N<<1];
 23 int n,tot,ptot;
 24 int lazy[MAX<<2];
 25 double pos[MAX],c[MAX<<2],cc[MAX<<2];
 26 void add(double x1,double x2,double y,int d)
 27 {
 28     tot++;
 29     g[tot] = {x1,x2,y,d};
 30 }
 31 void read()
 32 {
 33     tot = ptot = 0;
 34     scanf("%d",&n);
 35     for(int i=1;i<=n;i++)
 36     {
 37         double x1,y1,x2,y2;
 38         scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 39         add(x1,x2,y1,1);
 40         add(x1,x2,y2,-1);
 41         pos[++ptot] = x1;
 42         pos[++ptot] = x2;
 43     }
 44     sort(g+1,g+1+tot);
 45     sort(pos+1,pos+1+ptot);
 46     int m = 1;
 47     for(int i=2;i<=ptot;i++)
 48     {
 49         if(std::fabs(pos[i]-pos[i-1]) > eps)
 50         {
 51             pos[++m] = pos[i];
 52         }
 53     }
 54     ptot = m;
 55 }
 56
 57 int Find(double x)
 58 {
 59     int L = 1, R = ptot;
 60     while(L <= R)
 61     {
 62         int mid = L + R >> 1;
 63         if(std::fabs(pos[mid]-x) <= eps) return mid;
 64         else if(pos[mid] < x) L = mid + 1;
 65         else R = mid - 1;
 66     }
 67     return -1;
 68 }
 69
 70 void pushup(int o,int l,int r)
 71 {
 72     if(lazy[o] > 0) c[o] = pos[r] - pos[l-1];
 73     else if(l == r) c[o] = 0;
 74     else c[o] = c[ls] + c[rs];
 75     /*************************/
 76     if(lazy[o] >= 2) cc[o] = pos[r] - pos[l-1];
 77     else if(l == r) cc[o] = 0;
 78     else if(lazy[o] == 1) cc[o] = c[ls] + c[rs];
 79     else cc[o] = cc[ls] + cc[rs];
 80 }
 81
 82 void update(int o,int l,int r,int ql,int qr,int f)
 83 {
 84     if(ql == l && qr == r)
 85     {
 86         lazy[o] += f;
 87         pushup(o,l,r);
 88         return ;
 89     }
 90     if(qr <= t_mid) update(lson,ql,qr,f);
 91     else if(ql > t_mid) update(rson,ql,qr,f);
 92     else
 93     {
 94         update(lson,ql,t_mid,f);
 95         update(rson,t_mid+1,qr,f);
 96     }
 97     pushup(o,l,r);
 98 }
 99
100 void solve()
101 {
102     memset(lazy,0,sizeof(lazy));
103     memset(c,0,sizeof(c));
104     memset(cc,0,sizeof(cc));
105     double ans = 0;
106     for(int i=1;i<=tot;)
107     {
108         int j = i;
109         while(j <= tot && std::fabs(g[i].y-g[j].y) <= eps)
110         {
111             int L = Find(g[j].x1);
112             int R = Find(g[j].x2);
113             /*
114             下面的L要加1是因为两个点重合但是其实线段是不重合的,
115             所以线段树内不能让他们管辖同一块地方
116             而pushup里面再L减1是因为,计算两点之间的距离要用原来的点算
117             */
118             update(1,0,MAX,L+1, R, g[j].d);
119             j++;
120         }
121         if(j <= tot) ans += 1.0*(g[j].y-g[i].y) * cc[1];
122         i = j;
123     }
124     printf("%.2f\n",ans);
125 }
126
127 int main()
128 {
129     int T;
130     scanf("%d",&T);
131     while(T--)
132     {
133         read();
134         solve();
135     }
136     return 0;
137 }
时间: 2024-10-17 07:57:15

HDU 1255 覆盖的面积 ——(线段树+扫描线)的相关文章

hdu 1255 覆盖的面积(线段树&amp;扫描线&amp;重复面积)

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3375    Accepted Submission(s): 1645 Problem Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数

hdu 1255 覆盖的面积 线段树扫描线求重叠面积

稀里糊涂打完了没想到1A了,心情还是很舒畅的,c和c++的四舍五入还是四舍六入遇积进位遇偶舍,我感觉很混乱啊,这道题我输出的答案是7.62,也就是遇偶舍了,可是我就手动处理一下进位问题,发现0.005 系统自动进位0.01了,尼玛啊,我一下子就混乱了,不是遇偶舍么,0也是偶数啊,怎么就进位了呢.最后我就不手动处理进位问题了,直接0.2lf%,虽然我输出的结果是7.62,但是提交也过了 这道题和poj1151,hdu1542差不多,扫描线详细讲解http://blog.csdn.net/young

HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化一下,数据大小就缩小了,那么之后只需要线段树单点更新就好了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <map> 5 #include <algor

HDU 1255 覆盖的面积 线段树+扫描线

同 POJ1151 这次是两次 #include <iostream> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cstring> #include <string> #include <stack> #include <queue> #include <cmath> #include <vector

HDU 1255 覆盖的面积 (线段树 + 离散化 + 扫描线)

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4304    Accepted Submission(s): 2139 Problem Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数

HDU 1255 覆盖的面积(线段树面积并)

描述 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000. 注意:本题的输入数据较多,推荐使用scanf读入数据. Output 对于每组测试数据,请计算出

hdu1255 覆盖的面积 线段树-扫描线

矩形面积并 线段树-扫描线裸题 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 using namespace std; 6 const int maxm=2e3+5; 7 const double eps=1e-5; 8 9 struct seg{ 10 double x,y1,y2; 11 int c; 12 bool operator

HDU 1255 覆盖的面积 (扫描线 线段树 离散化)

题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了,因为虽然现在都不等于 2,但是之前的那个线段加上现在的已经覆盖2次了. 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include &

hdu 1255 覆盖的面积(扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1255 一道挺简单的题,让我折腾了许久.主要卡在了更新节点后维护父亲节点上.后来思路明确了就很容易了. 节点信息: l,r:区间端点 cnt:区间被覆盖的次数,cnt = 0说明没有被完全覆盖. len1:区间被覆盖的长度 len2:区间至少被两条线段覆盖的长度. 只要找到父亲节点与子节点在len1,len2,cnt的关系就简单了. #include <stdio.h> #include <iostre

HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

Problem A : Counting Squares From:HDU, 1264 Problem Description Your input is a series of rectangles, one per line. Each rectangle is specified as two points(X,Y) that specify the opposite corners of a rectangle. All coordinates will be integers in t