HDU 1255 覆盖的面积(线段树+扫描线求面积【升级版】)
2016-08-23 01:56
288 查看
http://www.cnblogs.com/scau20110726/archive/2013/04/14/3020998.html
这讲得太好了,感觉做了这题对于面积覆盖的题更理解了
之前写过 HDU 1542 是单纯的的求面积,这题在单纯的求面积上小小改动即可求两次覆盖以上的面积
题目链接:HDU 1255 覆盖的面积
两份代码对比下:
另外 这题很神奇的是,样例一给的答案7.63,AC代码算出的7.62。。。
这讲得太好了,感觉做了这题对于面积覆盖的题更理解了
之前写过 HDU 1542 是单纯的的求面积,这题在单纯的求面积上小小改动即可求两次覆盖以上的面积
题目链接:HDU 1255 覆盖的面积
两份代码对比下:
HDU 1542:
#define mem(a,x) memset(a,x,sizeof(a)) #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<stack> #include<cmath> #include<map> #include<stdlib.h> #include<cctype> #include<string> #define Sint(n) scanf("%d",&n) #define Sll(n) scanf("%I64d",&n) #define Schar(n) scanf("%c",&n) #define Schars(s) scanf("%s",s) #define Sint2(x,y) scanf("%d %d",&x,&y) #define Sll2(x,y) scanf("%I64d %I64d",&x,&y) #define Pint(x) printf("%d",x) #define Pllc(x,c) printf("%I64d%c",x,c) #define Pintc(x,c) printf("%d%c",x,c) using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int N = 111; struct Edge { double l,r; double h; int f; }e[N<<1]; bool cmp(Edge a,Edge b) { return a.h < b.h; } struct Node { int l,r; int s; double len; }q[N*8]; double x[N<<1]; #define ls i<<1 #define rs i<<1|1 #define m(i) ((q[i].l+q[i].r)>>1) void pushup(int i) { if (q[i].s) { q[i].len = x[q[i].r+1] - x[q[i].l]; } else if (q[i].l == q[i].r) q[i].len = 0; else q[i].len = q[ls].len + q[rs].len; } void build(int i,int l,int r) { q[i].l = l,q[i].r = r,q[i].s = 0;q[i].len = 0; if (l == r) return ; int mid = m(i); build(ls,l,mid); build(rs,mid+1,r); } void update(int i,int l,int r,int f) { if (l == q[i].l &&q[i].r == r) { q[i].s += f; pushup(i); return ; } int mid = m(i); if (r <= mid) update(ls,l,r,f); else if (l > mid) update(rs,l,r,f); else { update(ls,l,mid,f); update(rs,mid+1,r,f); } pushup(i); } int main() { int n;int kas = 0; while (Sint(n)&&n) { int tot = 0; for (int i = 1;i <= n;++i,tot+=2) { double x1,x2; double y1,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); Edge &t1 = e[tot],&t2 = e[tot+1]; t1.l = x1,t1.r = x2,t1.h = y1,t1.f = 1;//上边是1 t2.l = x1,t2.r = x2,t2.h = y2,t2.f = -1;//下边是-1 x[tot] = x1,x[tot+1] = x2; } sort(x,x+tot);sort(e,e+tot,cmp); int k = 1; //x[0] for (int i = 1;i < tot;++i) { if (x[i]!=x[i-1]) { x[k++] = x[i]; } } build (1,0,k-1);//离散后区间是[0,k-1] double ans = 0.0; for (int i = 0;i < tot;++i) { int l = lower_bound(x,x+k,e[i].l) - x;//找到实际坐标对应的离散坐标 int r = lower_bound(x,x+k,e[i].r) - x - 1; update(1,l,r,e[i].f); ans += q[1].len*(e[i+1].h-e[i].h); } printf("Test case #%d\n",++kas); printf("Total explored area: %.2f\n",ans); puts(""); } return 0; }
HDU 1255 :
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #define mem(a,x) memset(a,x,sizeof(a)) using namespace std; typedef long long ll; const int N = 1004; struct Edge //扫描线 { double l,r; double h; int f;//上边1 下边-1 } e[N<<1]; bool cmp(Edge a,Edge b) { return a.h < b.h; } struct Node { int l,r; int s;//该区间的覆盖状态 double len1;//该区间内被覆盖1次及以上的长度 double len2;//该区间内被覆盖2次及以上的长度 }q[(2*N)<<2];//一个矩形有2个横坐标 记得要先乘2 double x[N<<1]; #define ls i<<1 #define rs i<<1|1 #define m(i) ((q[i].l + q[i].r)>>1) void pushup(int i) { if (q[i].s) q[i].len1 = x[q[i].r+1] - x[q[i].l];//整个区间被覆盖 else if (q[i].l == q[i].r) q[i].len1 = 0;//叶子 else q[i].len1 = q[ls].len1 + q[rs].len1; /***************************下面是不同于一般的面积覆盖问题的地方************************/ if (q[i].s > 1) q[i].len2 = x[q[i].r+1] - x[q[i].l];//该区间被覆盖2次及以上 else if (q[i].l == q[i].r) q[i].len2 = 0; else if (q[i].s == 1) q[i].len2 = q[ls].len1 + q[rs].len1; else q[i].len2 = q[ls].len2 + q[rs].len2; } void build(int i,int l,int r) { q[i].l = l,q[i].r = r; q[i].s = q[i].len1 = q[i].len2 = 0; if (l == r) return; int mid = m(i); build(ls,l,mid); build(rs,mid+1,r); } void update(int i,int l,int r,int f) { if (l == q[i].l && q[i].r == r) { q[i].s += f; pushup(i); return ; } int mid = m(i); if (r <= mid) update(ls,l,r,f); else if (l > mid) update(rs,l,r,f); else { update(ls,l,mid,f); update(rs,mid+1,r,f); } pushup(i); } int main() { int T;cin>>T; while (T--) { int n;scanf("%d",&n); int tot = 0; double x1,x2,y1,y2; for (int i = 1;i <= n;++i) { scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2); Edge &t1 = e[tot],&t2 = e[tot+1]; t1.l = t2.l = x1,t1.r = t2.r = x2; t1.h = y1,t1.f = 1; t2.h = y2,t2.f = -1; x[tot] = x1,x[tot+1] = x2; tot += 2; } sort(x,x+tot); sort(e,e+tot,cmp); int k = 1; for (int i = 1;i < tot;++i)//去重 { if (x[i] != x[i-1]) x[k++] = x[i]; } build (1,0,k-1); double ans = 0.0; for (int i = 0;i < tot;++i) { int l = lower_bound(x,x+k,e[i].l) - x; int r = lower_bound(x,x+k,e[i].r) - x - 1; update(1,l,r,e[i].f); ans += q[1].len2*(e[i+1].h - e[i].h); } printf("%.2f\n",ans); } return 0; }
另外 这题很神奇的是,样例一给的答案7.63,AC代码算出的7.62。。。
相关文章推荐
- HDU 1255 覆盖的面积 (扫描线 线段树 离散化 矩形面积并)
- 【线段树 && 扫描线 && 面积交】HDU - 1255 覆盖的面积
- hdu 1255 覆盖的面积 线段树扫描线求重叠面积
- HDU 1255 覆盖的面积 (线段树 + 离散化 + 扫描线)
- hdu 1255 覆盖的面积 (线段树 扫描线)
- hdu 1255 覆盖的面积 (线段树 扫描线)
- HDU - 1255 覆盖的面积(线段树 + 扫描线)
- hdu 1255 覆盖的面积 (线段树扫描线 计算两次覆盖的面积)
- HDU - 1255 覆盖的面积(线段树 扫描线)
- 【 HDU 1255】 覆盖的面积(矩阵面积交,线段树,扫描法)
- HDU 1255 覆盖的面积[离散化 + 扫描线 + 线段树]
- HDU 1255 覆盖的面积(线段树扫描线求面积的交)
- HDU 1255 覆盖的面积 线段树 扫描线
- HDU 1255 覆盖的面积[离散化 + 扫描线 + 线段树]
- HDU 1255 - 覆盖的面积 (线段树 扫描线 面积交)
- HDU-1255 覆盖的面积(线段树扫描线模板+离散化+加点修改题)
- 覆盖的面积 HDU - 1255 线段树-扫描线
- HDU-1255 覆盖的面积 线段树 + 扫描线
- hdu 1255 覆盖的面积(线段树|扫描线)
- HDU 1255 覆盖的面积 线段树+扫描线求面积并