HDU 1255-覆盖的面积(线段树+扫描线)
2016-05-05 20:12
369 查看
C - 覆盖的面积
Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d
& %I64u
Submit Status Practice HDU
1255
Appoint description:
System Crawler (2016-04-30)
Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
![](http://7xjob4.com1.z0.glb.clouddn.com/d1adc6253c233d9968f03fe1d872f86d)
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
Sample Output
7.63
0.00
AC代码:
Time Limit:5000MS Memory Limit:32768KB 64bit IO Format:%I64d
& %I64u
Submit Status Practice HDU
1255
Appoint description:
System Crawler (2016-04-30)
Description
给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.
Input
输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.
注意:本题的输入数据较多,推荐使用scanf读入数据.
Output
对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
Sample Input
2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
Sample Output
7.63
0.00
AC代码:
/* 这题一开始是想找题解的,所以当我找了题解后,发现 有人一样是不会做这个的,只做了面积并,而且他YY过了 所以我也决定要YY过它,所以就没有看题解了。没想到 过了一晚时间就让我YY过了,哈哈!! */ #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> using namespace std; #define T 10005 #define lson (rt<<1) #define rson (rt<<1|1) typedef long long ll; int n; //离散化数组 double pos[T]; //保存y在x区间的边 struct line { double y,x_up,x_down; int flag; bool operator<(const line& a)const{ return y<a.y; } line(double _1,double _2,double _3,int _4): y(_1),x_up(_2),x_down(_3),flag(_4){} line(){} }p[T]; //线段树数组 struct node { int L,R; double len; int mid; int flag; }tree[T]; //向上更新 void pushup(int rt) { if(tree[rt].flag>=2){//完全覆盖区间 tree[rt].len = pos[tree[rt].R-1]-pos[tree[rt].L-1]; } else if(tree[rt].L+1==tree[rt].R){//叶子节点 tree[rt].len = 0; } else//跨越几个区间合并值 { tree[rt].len = tree[lson].len+tree[rson].len; /*tree[lson].len = 0,tree[rson].len=0;*/ } } /* 这题与面积并相像,只是多了一个向下更新,之所以要向下 更新是因为,我要的是单个区间都要有值 */ void pushdown(int rt) { if(tree[rt].flag){ tree[lson].flag += tree[rt].flag; tree[rson].flag += tree[rt].flag; tree[rt].flag = 0; } } //建树 void build(int rt,int L,int R) { tree[rt].L = L; tree[rt].R = R; tree[rt].flag = 0; tree[rt].len = 0; tree[rt].mid = (L+R)>>1; if(L+1!=R){ build(lson,L,tree[rt].mid); build(rson,tree[rt].mid,R); } } //更新 void update(int rt,int L,int R,int w) { /* 一开始答案存在偏差,弄了好久发现只要符合范围就返回 所以有些区间是将值传递下去了,结果却因为没下去所以 漏掉了一些面积,之后一直在调整pushdown函数,结果一直 没结果,换成只在区间才返回后就不存在这种情况了。应该 可以用懒惰性标记吧 */ if(L<=tree[rt].L&&tree[rt].R<=R&&tree[rt].L+1==tree[rt].R){ tree[rt].flag+=w; pushup(rt); return; } pushdown(rt); if(R<=tree[rt].mid) update(lson,L,R,w); else if(L>=tree[rt].mid) update(rson,L,R,w); else{ update(lson,L,tree[rt].mid,w); update(rson,tree[rt].mid,R,w); } pushup(rt); } int main() { #ifdef zsc freopen("input.txt","r",stdin); #endif int i,c,N; double x1,x2,y1,y2; scanf("%d",&N); while(N--) { scanf("%d",&n); c = 0; for(i=0;i<n;++i){ scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); pos[c] = x1; p[c++] = line(y1,x1,x2,1); pos[c] = x2; p[c++] = line(y2,x1,x2,-1); } sort(pos,pos+c); int d = unique(pos,pos+c)-pos; build(1,1,d); sort(p,p+c); double ans=0; for(i=0;i<c-1;++i){ //因为离散化了,所以要找x的下标 int a = lower_bound(pos,pos+d,p[i].x_up)-pos+1; int b = lower_bound(pos,pos+d,p[i].x_down)-pos+1; //更新x区间(a,b)的值 update(1,a,b,p[i].flag); ans+=tree[1].len*(p[i+1].y-p[i].y); } printf("%.2lf\n",ans); } return 0; }
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- 线段树题集
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- POJ1050 最大子矩阵和
- 用单调栈解决最大连续矩形面积问题
- 线段树
- 2632 Crashing Robots的解决方法