HDU 1255 覆盖的面积(线段树扫描线求面积的交)

Problem 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
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)

#define eps 1e-8
#define ll long long

#define fre(i,a,b)  for(i = a; i <b; i++)
#define free(i,b,a) for(i = b; i >= a;i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define ssf(n)      scanf("%s", n)
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define bug         pf("Hi\n")

using namespace std;

#define INF 0x3f3f3f3f

#define N 10005

struct stud{
 double x1,x2,h;
 int type;
 bool operator <(const stud b) const
 {
 	return h<b.h;
 }
}e[N];

struct studd{
  int le,ri;
  int cover;
  double once,len;
}f[N];

map<double,int>mp;

double x[N];

void build(int pos,int le,int ri)
{
	f[pos].le=le;
	f[pos].ri=ri;
	f[pos].cover=0;
	f[pos].once=f[pos].len=0;
	if(le+1==ri) return ;

	int mid=MID(le,ri);
	build(L(pos),le,mid);
	build(R(pos),mid,ri);
}

void pushup(int pos)
{
    if(f[pos].cover>=2)
	{
		f[pos].len=x[f[pos].ri]-x[f[pos].le];
		f[pos].once=0;
		return ;
	}

    if(f[pos].cover==1)   //这个区间被覆盖一次,那么两次的应该是下面的两次的加下面的一次的
	{
		if(f[pos].le+1==f[pos].ri)
		{
			f[pos].len=0;
			f[pos].once=x[f[pos].ri]-x[f[pos].le];
		}
        else
		{
			f[pos].len=f[L(pos)].len+f[L(pos)].once+f[R(pos)].len+f[R(pos)].once;
			f[pos].once=x[f[pos].ri]-x[f[pos].le]-f[pos].len;
		}
       return ;
	}

    if(f[pos].le+1==f[pos].ri)
	{
		f[pos].len=f[pos].once=0;
	}
    else
	{
		f[pos].len=f[L(pos)].len+f[R(pos)].len;
		f[pos].once=f[L(pos)].once+f[R(pos)].once;
	}

}

void update(int pos,int le,int ri,int type)
{
	if(f[pos].le>=le&&f[pos].ri<=ri)
	{
		f[pos].cover+=type;
		pushup(pos);
		return ;
	}
    int mid=MID(f[pos].le,f[pos].ri);

    if(mid>le)
		update(L(pos),le,ri,type);

	if(mid<ri)
		update(R(pos),le,ri,type);

	pushup(pos);
}

int main()
{
   int i,j,n,k,t;
   double x1,x2,y1,y2;

   sf(t);
   while(t--)
   {
   	 sf(n);
   	 k=0;
   	 fre(i,0,n)
   	 {
   	 	 scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
   	 	 if(x1>x2) swap(x1,x2);

   	 	 x[k]=x1;
   	 	 e[k].x1=x1;
   	 	 e[k].x2=x2;
   	 	 e[k].h=y1;
   	 	 e[k++].type=1;

   	 	 x[k]=x2;
   	 	 e[k].x1=x1;
   	 	 e[k].x2=x2;
   	 	 e[k].h=y2;
   	 	 e[k++].type=-1;
   	 }

   	 sort(x,x+k);
   	 sort(e,e+k);
   	 n=unique(x,x+k)-x;

   	 fre(i,0,n)
   	   mp[x[i]]=i;

   	 n--;

   	 build(1,0,n);

   	 double ans=0;

   	 fre(i,0,k-1)
   	 {
   	 	int le=mp[e[i].x1];
   	 	int ri=mp[e[i].x2];
   	 	update(1,le,ri,e[i].type);
   	 	ans+=f[1].len*(e[i+1].h-e[i].h);
   	 }
    pf("%.2f\n",ans);
   }
   return 0;
}
时间: 2024-08-28 22:20:52

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 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

poj 3277 City Horizon (线段树 扫描线 矩形面积并)

题目链接 题意: 给一些矩形,给出长和高,其中长是用区间的形式给出的,有些区间有重叠,最后求所有矩形的面积. 分析: 给的区间的范围很大,所以需要离散化,还需要把y坐标去重,不过我试了一下不去重 也不会出错, 所有的区间都能列出来,只是在查找的时候费点事. 给的矩形相当于在同一水平线上的,也就是y1坐标相当于为0,其他的就和 poj 1151 Atlantis 差不多了. 我写的思路是按照矩形面积并的思路写的: 但是还有另一种方法也是挺简单的,就是把给的矩形按照高从小到大排序,然后依次插入线段树

HDU 4419 Colourful Rectangle --离散化+线段树扫描线

题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何维护每种颜色的长度着实让我伤透了脑筋.后来看了一位朋友的题解,才幡然醒悟. 开始想到了用二进制表示颜色,R用001表示,G用010表示,B用100表示.那么就可以用十进制1~7表示7种不同颜色了. 维护 cov[rt][1~3] 表示此区间内3种原色各有多少个, Len[rt][i]表示每种颜色的长

HDU 3642 Get The Treasury 线段树+扫描线

反向标记是错的,要对矩形进行拆分 #include <cstdio> #include <algorithm> #include <cstring> #include <vector> typedef long long LL; using namespace std; #define lson rt << 1,l,mid #define rson rt << 1 | 1,mid + 1,r const int maxn = 5e4

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

线段树+扫描线求矩形面积的并

POJ 1151 Atlantis(线段树+扫描线) 参考博客https://blog.csdn.net/lwt36/article/details/48908031 上面博客的原理讲解非常清楚 在这我只对代码的模板分层讲解 一些基础的 #include <iostream> #include <cstdio> #include <string.h> #include <algorithm> #include <cmath> #define ls

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