hdu 1542 线段树+扫描线

啦啦啦~继续学算法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542

Atlantis

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 7349    Accepted Submission(s): 3231

Problem Description

There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your
friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

Input

The input file consists of several test cases. Each test case starts with a line containing a single integer n (1<=n<=100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2
(0<=x1<x2<=100000;0<=y1<y2<=100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area.

The input file is terminated by a line containing a single 0. Don’t process it.

Output

For each test case, your program should output one section. The first line of each section must be “Test case #k”, where k is the number of the test case (starting with 1). The second one must be “Total explored area: a”, where a
is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point.

Output a blank line after each test case.

Sample Input

2
10 10 20 20
15 15 25 25.5
0

Sample Output

Test case #1
Total explored area: 180.00 

参考自:http://blog.csdn.net/kk303/article/details/9493265

(1)注意double~ (2)用二分解决离散化的问题
#include <iostream>
#include <string>
#include <string.h>
#include <cstdio>
#include <algorithm>
const int N=220;
const double eps=1e-6;
using namespace std;
struct node
{
  double x1,x2,y;
  int tp;
}line[N*4];
bool cmp(node a,node b)
{
  return a.y-b.y<eps; //或者写成这样  return a.y-b.y<eps  有精度问题
}

int n,times[N*4];
double sum[N*4]; //隐式构建线段树
double xx[N*4];

int find(double x)
{
  int l=1,r=n;
  while(l<=r)
  {
   int mid=(l+r)/2;
   if(xx[mid]==x)return mid;
   else if(xx[mid]<x)l=mid+1;
   else r=mid;
  }
  return l;
}

void update(int x,int t,int l,int r,int v)
{
 if(l==r)
 {
   times[x]+=t;
   if(times[x])sum[v]=xx[x+1]-xx[x];
   else sum[v]=0;
   return;
 }
 int mid=(l+r)/2;
 if(x<=mid)update(x,t,l,mid,2*v);
 else update(x,t,mid+1,r,2*v+1);
 sum[v]=sum[2*v]+sum[2*v+1];
}

int main()
{
  int test=1;
  while(scanf("%d",&n)!=EOF)
  {
    if(n==0)break;
    memset(sum,0,sizeof(sum));
    memset(times,0,sizeof(times));
    memset(xx,0,sizeof(xx));

    int num=0;
    for(int i=1;i<=n;i++)
    {
     double x1,y1,x2,y2;
     scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
     line[++num].x1=x1;
     line[num].x2=x2;
     line[num].y=y1;
     line[num].tp=1;
     xx[num]=x1;

     line[++num].x1=x1;
     line[num].x2=x2;
     line[num].y=y2;
     line[num].tp=-1;
     xx[num]=x2;
    }
    n=n*2;
    sort(xx+1,xx+1+num);
    sort(line+1,line+1+num,cmp);
    double ans=0.0;
    for(int i=1;i<=num;i++)
    {
      ans+=sum[1]*(line[i].y-line[i-1].y);
      int l=find(line[i].x1);
      int r=find(line[i].x2)-1;
      for(int j=l;j<=r;j++)update(j,line[i].tp,1,n,1);
    }
    printf("Test case #%d\n",test++);
    printf("Total explored area: %.2lf\n",ans);
    printf("\n");
  }
  return 0;
}
时间: 2024-11-05 13:43:18

hdu 1542 线段树+扫描线的相关文章

HDU 1542 线段树+扫描线+离散化

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8327    Accepted Submission(s): 3627 Problem Description There are several ancient Greek texts that contain descriptions of the fabled is

HDU 5107 线段树扫描线

给出N个点(x,y),每个点有一个高度h 给出M次询问,问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对所有的点和询问进行离线操作,将询问和点按照x,y的大小排序,从左向右,从下向上,对于相同的(x,y)插入点在询问点之前 线段树的每个节点维护10个高度,每次询问[0,mark[i].y]的第mark[i].h高的值即可 #include "stdio.h" #include "string.h

hdu 1542 线段树之扫描线之面积并

点击打开链接 题意:给你n个矩形,求它们的面积,重复的不重复计算 思路:用线段树的扫描线完成,将X坐标离散化后,从下到上扫描矩形,进行各种处理,看代码注释把 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; con

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

http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所有的横坐标和纵坐标排序 因为是从左到右扫描,那么横坐标应该离散化一下 当扫描线依次扫描的时候,依次扫描到的纵区间在线段树中查找,依据是上边还是下边记录,上边就是-1,下边就是+1, 如果某区间记录值为0的时候,代表没有被覆盖,为1的时候代表覆盖一次,为2代表覆盖两次(不会出现为负数的情况) 最后将依

HDU 5091 线段树扫描线

给出N个点,和一个w*h的矩形 给出N个点的坐标,求该矩形最多可以覆盖多少个点 对每个点point(x,y)右边生成对应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍,遇到点则用该点的权值更新区间(y,y+h) #include "stdio.h" #include "string.h" #include "algorithm" using namespace std; struct Mark { int x,y,s; }ma

hdu 1264 线段树+扫描线

说实话  真是水题   题目给的数据太小  都不用离散化      之前用离散化处理一个类似的题 这道题是给你几个矩形    让你求覆盖面积    重复的只算一次 做完之后被坑了        题目说输入左下角和右下角坐标    但是     左上角和右下角也有可能   只要是对角就行    所有得线处理一下 #include<stdio.h> #include<iostream> #include<algorithm> #include<string.h>

HDU 2461 线段树扫描线

给出N个矩形,M次询问 每次询问给出R个,问这R个矩形围成的面积 经典扫面线求面积并,对每次询问的R个点离散化一下 #include "stdio.h" #include "string.h" #include "algorithm" #include "map" using namespace std; map<int,int>mp; struct P { int x1,y1,x2,y2; }p[21]; str

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek

hdu 1542 Atlantis(线段树&amp;扫描线&amp;面积并)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6386    Accepted Submission(s): 2814 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i