题意:给定平面直角坐标系中的N个矩形,求它们的面积并。

题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序。记录所有的y坐标以后排序离散化。离散化之后线段树的第i个叶子节点储存的是y[i+1]-y[i].

这里的线段树用的是一个不用下传延迟标记的做法(仅限这一类题)。线段树的每一个节点维护length(这个节点的子节点覆盖的长度)和cnt(这个节点代表的线段[l,r]所覆盖的次数)。

任意一个区间都可以被线段树划分成O(logn)个子区间,我们把这些节点的cnt值加上1或减去1。

在修改任意一个节点的cnt时或者向上维护信息的时候,如果这个节点的cnt>0,则这个节点所代表的区间覆盖的长度是y[r+1]-y[l],否则是子节点的长度和。

代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
map<double,int> mp;
const int maxn=200010;
struct ST{
int l,r,cnt;
double length;
}t[4*maxn];
struct node{
double x,y1,y2;
int k;
bool operator <(const node& rhs)const{
return x<rhs.x;
}
}a[maxn];
double b[maxn];
void build(int p,int l,int r){
t[p].l=l,t[p].r=r;
t[p].cnt=0;
t[p].length=0;
if(l==r){
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
void maintain(int p){
if(t[p].l==t[p].r)t[p].length=0;
else t[p].length=t[p*2].length+t[p*2+1].length;
}
void change(int p,int l,int r,int k){
if(l<=t[p].l&&r>=t[p].r){
t[p].cnt+=k;
if(t[p].cnt>0){
t[p].length=b[t[p].r+1]-b[t[p].l];
}
else
maintain(p);
return;
}
int mid=(t[p].l+t[p].r)/2;
if(mid>=l)change(p*2,l,r,k);
if(mid<r)change(p*2+1,l,r,k);
if(t[p].cnt>0)t[p].length=b[t[p].r+1]-b[t[p].l];
else maintain(p);
}
int main(){
int n,kase=0;
double x1,x2,y1,y2;
double ans=0;
while(~scanf("%d",&n)&&n){
ans=0;
mp.clear();
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a[i]=(node){x1,y1,y2,1};
a[i+n]=(node){x2,y1,y2,-1};
b[i]=y1,b[i+n]=y2;
}
sort(a+1,a+1+2*n);
sort(b+1,b+1+2*n);
int m=unique(b+1,b+1+2*n)-(b+1);
for(int i=1;i<=m;i++)
mp[b[i]]=i;
build(1,1,m-1);
for(int i=1;i<2*n;i++){
int l=mp[a[i].y1],r=mp[a[i].y2]-1;
change(1,l,r,a[i].k);
ans+=(a[i+1].x-a[i].x)*(t[1].length);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",++kase,ans);
}
return 0;
}

  

POJ 1151 扫描线 线段树的更多相关文章

  1. POJ 1151 - Atlantis 线段树+扫描线..

    离散化: 将所有的x轴坐标存在一个数组里..排序.当进入一条线段时..通过二分的方式确定其左右点对应的离散值... 扫描线..可以看成一根平行于x轴的直线..至y=0开始往上扫..直到扫出最后一条平行 ...

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

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

  3. hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]

    Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total S ...

  4. POJ 1151 Atlantis 线段树+离散化+扫描线

    这次是求矩形面积并 /* Problem: 1151 User: 96655 Memory: 716K Time: 0MS Language: G++ Result: Accepted */ #inc ...

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

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

  6. HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)

    Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...

  7. HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  8. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  9. POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)

    POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...

随机推荐

  1. 51nod 1163 贪心

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1163 1163 最高的奖励 基准时间限制:1 秒 空间限制:131072 ...

  2. MongoDB3.0 创建用户

    use mydb db.createUser( { "user" : "sa", "pwd": "sa", " ...

  3. orale存储技术

    一.存储的主要作用 1.海量存储 阵列存储   光盘存储   磁带存储   数据迁移   文件服务器,跨平台文件共享 2.容灾 数据备份及恢复:磁带.光盘.阵列  数据复制:本地镜像.远程镜像 3.高 ...

  4. JVM和Dalvik VM的简要区别

    一.结构 JVM是栈堆   Dalvik VM是寄存器 二.编译 JVM:.java>.class>.jar Dalvik VM:.java>.class>.dex>.o ...

  5. Windows之IOCP

    IOCP全称I/O Completion Port,中文译为I/O完成端口.IOCP是一个异步I/O的Windows API,它可以高效地将I/O事件通知给应用程序,类似于Linux中的Epoll,关 ...

  6. Spring转账业务_XML配置事物控制

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  7. asp.net core mcroservices 架构之 分布式日志(一)

    一 简介 无论是微服务还是其他任何分布式系统,都需要一个统一处理日志的系统,这个系统 必须有收集,索引,分析查询的功能.asp .net core自己的日志是同步方式的,正如文档所言: 所以必须自己提 ...

  8. 利用TaskScheduler处理Queue、Stack等类型的操作队列(生产者消费者场景)

    我们经常会遇到生产者消费者模式,比如前端各种UI操作事件触发后台逻辑等.在这种典型的应用场景中,我们可能会有4个业务处理逻辑(下文以P代表生产者,C代表消费者): 1. FIFO(先进先出)     ...

  9. ODP.NET OracleBulkCopy

    using System;using System.Collections.Generic;using System.Linq;using System.Text;using Oracle.DataA ...

  10. Composer + thinkphp5.1安装与使用

    Composer 是 PHP 的一个依赖管理工具.我们可以在项目中声明所依赖的外部工具库,Composer 会帮你安装这些依赖的库文件,有了它,我们就可以很轻松的使用一个命令将其他人的优秀代码引用到我 ...