Area Coverage
Time Limit: 10000ms, Special Time Limit:2500ms, Memory Limit:65536KB
Total submit users: 16, Accepted users: 12
Problem 12884 : No special judgement
Problem description

In this day and age, a lot of the spying on other countries is done with the use of satellites and drones equipped with cameras. All these photographs of various sizes and from various sources can be combined to give a picture of the country as a whole.
Given the photographs (that is to say, the rectangular
area covered by each, since the contents of the photographs themselves are of
course top-secret!), can you work out what the total area is of all that is
photographed? Note that certain areas can appear on multiple photographs and
should be counted only once.

Input

On the first line one positive number: the number of test cases, at most 100.
After that per test case:
one line with an integer n (1<=n<=1000):
the number of photographs.
n lines with four space-separated integers x1,
y1, x2 and y2 (0<=x1; y1; x2; y2<=1 000 000, x1 < x2 and y1 < y2):
the coordinates of the southwest and northeast corner, respectively, of each
photograph. The photographs are all rectangular in shape with their other
corners at (x1; y2) and (x2; y1).
The coordinates correspond to a flat
two-dimensional space (i.e. we assume the Earth to be
flat).

Output

Per test case:
one line with an integer: the total area of all that
appears on the photographs.

Sample Input
  1. 2
  2. 3
  3. 0 6 20 16
  4. 14 0 24 10
  5. 50 50 60 60
  6. 2
  7. 0 0 20 10
  8. 10 4 14 8
Sample Output
  1. 376
  2. 200
Problem Source
BAPC preliminary 2013

Mean:

在二维平面中,给你一些矩形的左下坐标(x1,y1)和右上坐标(x2,y2),让你求这些矩形面积的并。

analyse:

我们在y轴方向上维护一棵线段树。该线段树的模型是区间覆盖,即应该对像某个区间有没有被覆盖这样的查询,以及添加覆盖和删除覆盖这样的操作---也就是将矩形的左右两边界看作对y轴的覆盖来处理。我们将所有矩形的左右边界按照x坐标升序排序。每个矩形的左边界执行对y轴的覆盖操作,右边界执行对x轴的删除覆盖操作。

每次插入一条线段的时候,我们判断cover值(覆盖的次数),如果>0那么就算面积。

如图:

初始时每条线段的cover都为0;

线段1插入后,所对应的区间cover变为1,当第二条线段插入时,我们先判断一下该区间上的cover值,发现有一段cover是大于0的,所以就将对应的面积(蓝色部分)加入ans中,此时线段2下半部分的cover值变为2,上部分的cover值变为1,还要把线段1的上部分的x坐标更新为线段2的x值;

当第三条直线插入时,同样的道理,加入的是黄色部分的面积;第四条进入时,加入的是紫色部分的面积。

这样,我们只需要在插入前先计算面积,当所有线段插入结束,answer也就出来了。

所以我们的线段树只需要两个函数:build和insert函数。

Time complexity:O(n*logn)

Source code:

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-07-23-20.40
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#define  LL long long
#define  ULL unsigned long long
using namespace std;

const int N = ;
double y[ * N];
struct LINE
{
     double x, y_down, y_up;
     int flag;//左线段or右线段
};
LINE line[N << ];
struct Tree
{
     int x;
     int cover;        // 覆盖次数
     bool flag;         // 是否为叶子节点
     int y_up, y_down;
};
Tree tree[( << ) * ];
bool cmp( LINE a, LINE b )
{
     return a.x < b.x;
}
void build( int l, int r, int x )
{
     tree[x].x = -; //-1表示该区间没有线段
     tree[x].cover = ;
     tree[x].flag = false;
     tree[x].y_up = y[r];
     tree[x].y_down = y[l];
     if( l + == r ) // 叶子结点: (1,2) (2,3) (3,4) (4,5)....
     {
           tree[x].flag = true;
           return;
     }
     int tmp = x << ;
     int mid = ( l + r ) >> ;
     build( l, mid, tmp );
     build( mid, r, tmp + );;
}
double insert( int i, double x, double l, double r, int flag )
{
     if( r <= tree[i].y_down || l >= tree[i].y_up ) //要插入的线段不在该区间
           return ;
     if( tree[i].flag ) //叶子节点
     {
           if( tree[i].cover > )     // 需要求并面积
           {
                 double temp_x = tree[i].x;
                 double ans = ( x - temp_x ) * ( tree[i].y_up - tree[i].y_down ); // 宽*高
                 tree[i].x = x; // 更新树中的x值
                 tree[i].cover += flag;
                 return ans;
           }
           else
           {
                 tree[i].cover += flag;
                 tree[i].x = x;
                 return ;
           }
     }
     double ans1, ans2;
     int tmp = i << ;
     ans1 = insert( tmp, x, l, r, flag );
     ans2 = insert( tmp + , x, l, r, flag );
     return ans1 + ans2;
}

int main()
{
     ios_base::sync_with_stdio( false );
     cin.tie( );
     int T;
     cin >> T;
     double x1, y1, x2, y2;
     while( T-- )
     {
           int n;
           cin >> n;
           int index = ;
           for( int i = ; i <= n; i++ )
           {
                 scanf( "%lf %lf %lf %lf", &x1, &y1, &x2, &y2 );
                 y[index] = y1;
                 line[index].x = x1;
                 line[index].y_down = y1;
                 line[index].y_up = y2;
                 line[index].flag = ;
                 index++;
                 y[index] = y2;
                 line[index].x = x2;
                 line[index].y_down = y1;
                 line[index].y_up = y2;
                 line[index].flag = -;
                 index++;
           }
           index--;
           double ans = 0.0;
           sort( line + , line + + index, cmp );
           sort( y + , y + + index );
           build( , index, );
           for( int i = ; i <= index; i++ )
           {
                 ans += insert( , line[i].x, line[i].y_down, line[i].y_up, line[i].flag );
           }
           printf( "%.0lf\n", ans );
     }
     return ;
}

扫描线 + 线段树 : 求矩形面积的并 ---- hnu : 12884 Area Coverage的更多相关文章

  1. POJ 1151Atlantis 扫描线+线段树求矩形面积并

    题目链接 #include <iostream> #include <vector> #include <cstdio> #include <cstring& ...

  2. HDU - 1255 覆盖的面积(线段树求矩形面积交 扫描线+离散化)

    链接:线段树求矩形面积并 扫描线+离散化 1.给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. 2.看完线段树求矩形面积并 的方法后,再看这题,求的是矩形面积交,类同. 求面积时,用被覆 ...

  3. 【hdu1542】线段树求矩形面积并

    分割线内容转载自http://hzwer.com/879.html ------------------------------------------------------------------ ...

  4. POJ 1151 / HDU 1542 Atlantis 线段树求矩形面积并

    题意:给出矩形两对角点坐标,求矩形面积并. 解法:线段树+离散化. 每加入一个矩形,将两个y值加入yy数组以待离散化,将左边界cover值置为1,右边界置为2,离散后建立的线段树其实是以y值建的树,线 ...

  5. POJ 1151 Atlantis 线段树求矩形面积并 方法详解

    第一次做线段树扫描法的题,网搜各种讲解,发现大多数都讲得太过简洁,不是太容易理解.所以自己打算写一个详细的.看完必会o(∩_∩)o 顾名思义,扫描法就是用一根想象中的线扫过所有矩形,在写代码的过程中, ...

  6. 【hdu1255】线段树求矩形面积交

    题意大概就是上图这个样子.<=100组测试数据,每组<=1000个矩形. 题解: 这个问题怎么解决..做了上一题矩形面积并应该就会了.. 对于每个节点维护3个值: cnt:该节点所代表的这 ...

  7. HDU 1255 覆盖的面积 (扫描线 线段树 离散化 矩形面积并)

    题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了, ...

  8. UVA 11983 Weird Advertisement --线段树求矩形问题

    题意:给出n个矩形,求矩形中被覆盖K次以上的面积的和. 解法:整体与求矩形面积并差不多,不过在更新pushup改变len的时候,要有一层循环,来更新tree[rt].len[i],其中tree[rt] ...

  9. HDU 1542.Atlantis-线段树求矩形面积并(离散化、扫描线/线段树)-贴模板

    好久没写过博客了,这学期不是很有热情去写博客,写过的题也懒得写题解.现在来水一水博客,写一下若干年前的题目的题解. Atlantis Time Limit: 2000/1000 MS (Java/Ot ...

随机推荐

  1. 设计模式之美:Visitor(访问者)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):Visitor 模式结构样式代码. 实现方式(二):使用 Visitor 模式解构设计. 实现方式(三):使用 Acyclic ...

  2. 3、CC2541芯片中级教程-OSAL操作系统(ADC光敏电阻和修改串口波特率)

    本文根据一周CC2541笔记汇总得来—— 适合概览和知识快速索引—— 全部链接: 中级教程-OSAL操作系统\OSAL操作系统-实验01 OSAL初探 [插入]SourceInsight-工程建立方法 ...

  3. [FPGA] 2、新建并运行一个工程

    上一篇将开发板的情况大致介绍了一下,这次将一步一步展示如何新建.调试并下载运行一个点亮LED的工程. 1)打开Quartus新建工程: 2)填写规则大致如下: 3)选择我们芯片的类型: 4)点击fil ...

  4. iOS——Core Animation 知识摘抄(二)

    阴影 主要是shadowOpacity .shadowColor.shadowOffset和shadowRadius四个属性 shadowPath属性 我们已经知道图层阴影并不总是方的,而是从图层内容 ...

  5. Java-继承,多态-0922-04

    定义类Human,具有若干属性和功能:定义其子类Man.Woman: 在主类Test中分别创建子类.父类和上转型对象,并测试其特性. 父类: package com.lianxi3; public c ...

  6. 我心中的核心组件(可插拔的AOP)~第二回 缓存拦截器

    回到目录 AOP面向切面的编程,也称面向方面的编程,我更青睐于前面的叫法,将一个大系统切成多个独立的部分,而这个独立的部分又可以方便的插拔在其它领域的系统之中,这种编程的方式我们叫它面向切面,而这些独 ...

  7. NodeJS系列~第四个小例子,NodeJs处理Get请求和Post请求

    返回目录 说在前 对于HTTP请求来说,我们通常使用的是Get和Post,除此之外还有put,delete等,而对于get来说,比较lightweight,只是对字符串的传输,它会被添加到URL地址里 ...

  8. Node.js与Sails~自定义响应体responses

    回到目录 在Node.js里,你可以控制请求和响应,自己可以定义自己的响应方式,如对文本如何响应,对json如何响应,对图像流如何响应等等,而这些在Sails架构里,变得更加容易和清晰了,它位于项目的 ...

  9. WebApi系列~安全校验中的防篡改和防复用

    回到目录 web api越来越火,因为它的跨平台,因为它的简单,因为它支持xml,json等流行的数据协议,我们在开发基于面向服务的API时,有个问题一直在困扰着我们,那就是数据的安全,请求的安全,一 ...

  10. 【译】采用MVC模式创建一个简单的javascript App

    原文标题:Build A Simple Javascript App The MVC Way 作者:joshcrawmer4 翻译人:huansky 初次翻译,翻译的不好,还请见谅 JavaScrip ...