[Baltic 2001]Mars Maps

来源:互联网 发布:网络营销师和编程 编辑:程序博客网 时间:2024/05/18 14:11

Description

In the year 2051, several Mars expeditions have explored different areas of the red planet and produced maps of these areas. Now, the BaSA (Baltic Space Agency) has an ambitious plan: they would like to produce a map of the whole planet. In order to calculate the necessary effort, they need to know the total size of the area for which maps already exist. It is your task to write a program that calculates this area.
Task Write a program that:

  • reads the description of map shapes from the input file mar.in,
  • computes the total area covered by the maps,
  • writes the result to the output file mar.out.

题目大意:给你N个矩形,给出矩形对角坐标,要你求出这些矩形所覆盖的面积

Input

The input file mar.in starts with a line containing a single integer N (1<=N<=10 000) the number of available maps. Each of the following N lines describes a map. Each of these lines contains four integers x1, y1, x2 and y2 (0<=x1the coordinates of, respectively, the bottom-left and the top-right corner of the mapped area. Each map has rectangular shape, and its sides are parallel to the x- and y-axis of the coordinate system.

Output

The output should contain one integer A, the total explored area
(i.e. the area of the union of all rectangles).

Sample Input
2
10 10 20 20
15 15 25 30

Sample Output
225

这道题目是一个比较经典的题目,它用到了线段树扫描线这个方法。
扫描线是什么东西?
首先我们给出一张图,图中共有3个矩形,覆盖的总面积为24。
这里写图片描述
图中绿色的线即为扫描线。线段树上维护的信息为扫描线上的区间是否被覆盖。
扫描线从左方向右方移动,图中红色的边叫做起始边,黄色的边叫做终止边。在扫描线不断扫描的过程中,碰到起始边,我们就将起始边覆盖上去;碰到终止边时,就从扫描线上将其抹去。
这样做有什么用?
这里写图片描述
我们把关建边(起始边和终止边的统称)所在的位置标明出来。每两个关建边之间都有一段面积(图中相同颜色的为同一段),这些面积之和即为总覆盖面积。这些面积怎么算?
其实相信大家心中已经有了答案。
每一小段的面积,就是上一个关建边操作完之后,线段树上覆盖区间大小乘上两个关建边之间的距离。
所以接下来就是傻逼的处理和线段树的维护了。

#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define inf 0x7f7f7f7fusing namespace std;typedef long long ll;typedef unsigned int ui;typedef unsigned long long ull;inline int read(){    int x=0,f=1;char ch=getchar();    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';    return x*f;}inline void print(int x){    if (x>=10)     print(x/10);    putchar(x%10+'0');}const int N=5e4;struct AC{    int l,r,val,ID;    bool operator <(const AC &x)const{return val!=x.val?val<x.val:ID>x.ID;}//按横坐标排序,终止边要摆在起始边之前。至于为什么,见文章底}A[N];struct Segment{    #define ls (p<<1)    #define rs (p<<1|1)    int tree[N*16+10],Lazy[N*16+10];//线段树记录的就是一个个区间,而不是一个个坐标,因此主程序中使用r-1    void updata(int p,int l,int r){//区间覆盖大小的维护        if (Lazy[p])    tree[p]=r-l+1;        else    tree[p]=(l==r)?0:(tree[ls]+tree[rs]);    }    void change(int p,int l,int r,int x,int y,int t){//简单打标记        if (x<=l&&r<=y){            Lazy[p]+=t;            updata(p,l,r);            return;        }        int mid=(l+r)>>1;        if (x<=mid) change(ls,l,mid,x,y,t);        if (y>mid)  change(rs,mid+1,r,x,y,t);        updata(p,l,r);    }}T;int main(){    int n=read(),ans=0;    for (int i=1;i<=n;i++){        int a=read(),b=read(),c=read(),d=read();        A[i].ID=1,A[i+n].ID=-1;//ID记录是起始边还是结束边        A[i].val=a,  A[i].l=b,  A[i].r=d-1;//按关建边的x坐标排序,因此要记录,l,r即为区间左右边界        A[i+n].val=c,A[i+n].l=b,A[i+n].r=d-1;    }    sort(A+1,A+1+2*n);    for (int i=1;i<=2*n;i++){        if (i!=1)   ans+=(A[i].val-A[i-1].val)*T.tree[1];//i=1的时候没有什么东西可以加        T.change(1,-N,N,A[i].l,A[i].r,A[i].ID);    }    printf("%d\n",ans);    return 0;}

为什么在排序的时候,终止边要在起始边前面呢?
其实对于本题而言,并没有什么影响。
不过起始边和终止边的摆放位置对下一题有影响。
请参考ioi1998 Picture

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小吊车8吨多少钱 手工小吊车 移动小吊车 吊车小勾 吊车200吨 手动液压小吊车 1吨小吊车 农村小吊车 gta5吊车 小形吊车 吊车维修 小吊车起重机 唐骏小型吊车 小型吊车价格及图片 5吨小吊车价格 小型吊车5吨 小型吊车型号 小型吊车吧 吊车都有多少吨的 超级吊车 小型吊车价格表 吊车的图片 小型起重机多少钱 小型移动起重机 小型起重机图片 小型履带式起重机 电动小型起重机 塔吊吊重 徐工履带起重机 黄冈小状元同步作文 学科同步 同步卫星轨道半径是地球半径 初二上册数学同步 六年级上册数学同步辅导 小学三年级数学同步辅导 小后娘by月半丁 菩萨小后娘 倌琯 穿成女主她后娘 浅小秋 携美向仙 美颜向相机 宗子