POJ 1151 Atlantis(经典的线段树扫描线,求矩阵面积并)
求矩阵的面积并
采用的是区间更新
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define lson rt<<1,L,mid
#define rson rt<<1|1,mid+1,R
/*
AC
一开始一直WA的原因是,hashx写成了int型!!! 第一次用的是直接单点更新,这次用区间更新写写看
*/
using namespace std;
const int maxn=;
int n;
double x1,y1,x2,y2;
//题目中有误,题目说的是(x1,y1)为矩形的左上端点,(x2,y2)为矩形的右下端点,
//但是给出的值y1<y2。。。也就是说(x1,y1)为矩形的左下端点,(x2,y2)为矩形的右上端点
double hashx[maxn<<];
int idx;
int mark[maxn<<];
double sum[maxn<<];
struct Line{
double y,l,r;
int tp;
bool operator<(const Line tmp)const{
return y<tmp.y;
}
}line[maxn<<]; struct Node{
double sum;
int mark;
}tree[maxn<<]; void build(int rt,int L,int R){
tree[rt].sum=tree[rt].mark=;
if(L==R){
return ;
}
int mid=(L+R)>>;
build(rt<<,L,mid);
build(rt<<|,mid+,R);
} void pushUp(int rt,int L,int R){
if(tree[rt].mark){
tree[rt].sum=hashx[R+]-hashx[L];
}
else{
if(L==R)
tree[rt].sum=;
else
tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
}
}
void update(int rt,int L,int R,int l,int r,int val){
if(L==R){
//原本写了个tree[rt].mark。。。
tree[rt].mark+=val;
pushUp(rt,L,R);
return;
}
int mid=(L+R)>>;
if(r<=mid)
update(lson,l,r,val);
else if(l>mid)
update(rson,l,r,val);
else{
update(lson,l,mid,val);
update(rson,mid+,r,val);
}
pushUp(rt,L,R);
}
//二分搜索对应的映射,也可以用map建立double-int的映射关系
int binarySearch(double x){
int l=,r=n+,mid; //注意:l初试为0,r初试为n+1。否则若是1和n的话,若搜索的值为hashx[1]或者hashx[n]就错了。
while (r-l>) //这里若为r>l的话,就会陷入死循环。举例:l=1,r=2,mid=1,x>=hashx[1]。
{
mid=(l+r)>>;
if (hashx[mid]<=x) l=mid;
else r=mid;
}
return l;
} int main()
{
int a,b,t=;
while(scanf("%d",&n),n){
idx=;
t++;
for(int i=;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[*i-].y=y1;line[*i-].l=x1;line[*i-].r=x2;line[*i-].tp=;
line[*i].y=y2;line[*i].l=x1;line[*i].r=x2;line[*i].tp=-;
hashx[++idx]=x1;
hashx[++idx]=x2;
}
n=n*;
build(,,n);
sort(line+,line++n);
sort(hashx+,hashx+idx+);
double ans=;
for(int i=;i<=n;i++){
ans+=tree[].sum*(line[i].y-line[i-].y);
a=binarySearch(line[i].l);
b=binarySearch(line[i].r)-;
update(,,n,a,b,line[i].tp);
}
printf("Test case #%d\n",t);
printf("Total explored area: %.2lf\n\n",ans);
}
return ;
}
采用的是单点更新
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
/*
AC
*/
using namespace std;
const int maxn=;
int n;
double x1,y1,x2,y2;
//题目中有误,题目说的是(x1,y1)为矩形的左上端点,(x2,y2)为矩形的右下端点,
//但是给出的值y1<y2。。。也就是说(x1,y1)为矩形的左下端点,(x2,y2)为矩形的右上端点
double hashx[maxn<<];
int idx;
int mark[maxn<<];
double sum[maxn<<];
struct Line{
double y,l,r;
int tp;
bool operator<(const Line tmp)const{
return y<tmp.y;
}
}line[maxn<<]; struct Node{
double sum;
int mark;
}tree[maxn<<]; void build(int rt,int L,int R){
tree[rt].sum=tree[rt].mark=;
if(L==R){
return ;
}
int mid=(L+R)>>;
build(rt<<,L,mid);
build(rt<<|,mid+,R);
} void pushUp(int rt){
tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
}
void update(int rt,int x,int L,int R,int val){
if(L==R){
tree[L].mark+=val;
//mark[x]+=val;
if(tree[L].mark)
tree[rt].sum=hashx[x+]-hashx[x];
else
tree[rt].sum=;
return;
}
int mid=(L+R)>>;
if(x<=mid)
update(rt<<,x,L,mid,val);
else
update(rt<<|,x,mid+,R,val);
pushUp(rt);
}
//二分搜索对应的映射,也可以用map建立double-int的映射关系
int binarySearch(double x){
int l=,r=n+,mid; //注意:l初试为0,r初试为n+1。否则若是1和n的话,若搜索的值为hashx[1]或者hashx[n]就错了。
while (r-l>) //这里若为r>l的话,就会陷入死循环。举例:l=1,r=2,mid=1,x>=hashx[1]。
{
mid=(l+r)>>;
if (hashx[mid]<=x) l=mid;
else r=mid;
}
return l;
} int main()
{
int a,b,t=;
while(scanf("%d",&n),n){
idx=;
t++;
memset(mark,,sizeof(mark));
for(int i=;i<=n;i++){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
line[*i-].y=y1;line[*i-].l=x1;line[*i-].r=x2;line[*i-].tp=;
line[*i].y=y2;line[*i].l=x1;line[*i].r=x2;line[*i].tp=-;
hashx[++idx]=x1;
hashx[++idx]=x2;
}
n=n*;
build(,,n);
sort(line+,line++n);
sort(hashx+,hashx+idx+);
double ans=;
for(int i=;i<=n;i++){
ans+=tree[].sum*(line[i].y-line[i-].y);
a=binarySearch(line[i].l);
b=binarySearch(line[i].r)-;
for(int j=a;j<=b;j++)
update(,j,,n,line[i].tp);
}
printf("Test case #%d\n",t);
printf("Total explored area: %.2lf\n\n",ans);
}
return ;
}
POJ 1151 Atlantis(经典的线段树扫描线,求矩阵面积并)的更多相关文章
- hdu1542 线段树扫描线求矩形面积的并
题意: 给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路: 自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...
- HDU 1542"Atlantis"(线段树+扫描线求矩形面积并)
传送门 •题意 给你 n 矩形,每个矩形给出你 $(x_1,y_1),(x_2,y_2)$ 分别表示这个矩形的左下角和右上角坐标: 让你求这 n 个矩形并的面积: 其中 $x \leq 10^{5} ...
- hdu1828 线段树扫描线求矩形面积的周长
题意: 给你n个矩形,问你这n个矩形所围成的图形的周长是多少. 思路: 线段树的扫描线简单应用,这个题目我用的方法比较笨,就是扫描两次,上下扫描,求出多边形的上下边长和,然后同 ...
- 2015 UESTC 数据结构专题E题 秋实大哥与家 线段树扫描线求矩形面积交
E - 秋实大哥与家 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/contest/show/59 De ...
- hdu 1542&&poj 1151 Atlantis[线段树+扫描线求矩形面积的并]
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- Atlantis HDU - 1542 线段树+扫描线 求交叉图形面积
//永远只考虑根节点的信息,说明在query时不会调用pushdown //所有操作均是成对出现,且先加后减 // #include <cstdio> #include <cstri ...
- hdu1542 Atlantis 线段树--扫描线求面积并
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- POJ 3264 Balanced Lineup【线段树区间查询求最大值和最小值】
Balanced Lineup Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 53703 Accepted: 25237 ...
随机推荐
- spring aop 使用注解方式总结
spring aop的注解方式:和xml的配置方式略有区别,详细如下: 1.首先还是建立需要的切面类:切面类里面定义好切点配置,以及所有的需要实现的通知方法. /** * */ package com ...
- eclipse java.lang.OutOfMemoryError: Java heap space
1.手动编译运行需要添加 java -Xms256m -Xmx1024m classname 2.在eclipse中,在run as -> run configurations -> ar ...
- golang实现ping命令
// Copyright 2009 The Go Authors. All rights reserved.// Use of this source code is governed by a B ...
- 浅析Objective-C字面量
编写Objective-C程序时,总会用到某几个类,它们属于Foundation框架.虽然从技术上来说,不用Foundation框架也能写出Objective-C代码,但实际上却经常要用到此框架.这几 ...
- PHP中使用CURL实现GET和POST请求
转自:http://www.smsyun.com/home-index-page-id-284.html 一.什么是CURL? cURL 是一个利用URL语法规定来传输文件和数据的工具,支持很多协议, ...
- 网页设计师必备的10个CSS技巧
CSS是网页设计师的基础,对CSS的了解能使他们能够设计出更加美观别致的网页.使用CSS技巧来巧妙地处理CSS是非常令设计师着迷的事情.在CSS的深海世界里有很多有意思的东西,你只需要找到最适合你的就 ...
- Unity使用Kinect初级教程
准备 首先,你需要准备的东西 Windows 8以上系统的电脑,当然,配置不要太渣⊙︿⊙ Kinect for Windows开发套件 安装好Kinect for Windows SDK,这个应该属于 ...
- snmp数据包分析
今天看了一下snmp数据包的报文格式,用wireshark抓了两个数据包来分析. 先说说snmp get-request的书报包格式吧,get-next-request,get-response,se ...
- 老叶观点:MySQL开发规范之我见
来源:http://ourmysql.com/archives/1396 大多数MySQL规范在网上也都能找得到相关的分享,在这里要分享的是老叶个人认为比较重要的,或者容易被忽视的,以及容易被混淆的一 ...
- 软件工程随堂小作业——(C++)
一.设计思路 本来我的思路是根据上楼的人数和上楼的层数来计算出平均值,但是我发现这个思路不对.于是我选择了最笨的方法,复杂度为O(n2). (1)输入坐电梯的人数和要去的楼层: (2)找到输入楼层里最 ...