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 ...
随机推荐
- Python科学计算利器——Anaconda
(搬运自我在SegmentFault的博客) 最近在用Python做中文自然语言处理.使用的IDE是PyCharm.PyCharm确实是Python开发之首选,但用于科学计算方面,还略有欠缺.为此我尝 ...
- 使用Telerik控件搭建Doubanfm频道部分
今天感觉好累啊..还是坚持记录下. 收集的API: https://github.com/HakurouKen/douban.fm-api https://github.com/zonyitoo/do ...
- Python 以正确的宽度在盒子中居中打印一个字符
注意://为整除的意思 代码: # -*- coding:UTF-8 -*- sentence = input("Sentence:") screen_width = 80 tex ...
- Oracle redo 日志切换时间频率
DB: 11.2.0.3.0 查看Oracle的redo日志切换频率 两条SQL,原理是一样的,第二个用到了统计函数 时间单位:分钟 方法一. select * from v$log a where ...
- CSS3中新出现的技术
CSS3中新出现的技术 CSS媒体查询 媒体查询 包含了一个媒体类型和至少一个使用如宽度.高度和颜色等媒体属性来限制样式表范围的表达式.CSS3加入的媒体查询使得无需修改内容便可以使样式应用于某些特定 ...
- SQL Server 批量插入数据的两种方法
在SQL Server 中插入一条数据使用Insert语句,但是如果想要批量插入一堆数据的话,循环使用Insert不仅效率低,而且会导致SQL一系统性能问题.下面介绍 SQL Server支持的两种批 ...
- Linux获取线程tid线程名
Linux获取线程tid线程名 1 2 3 4 5 6 //thread name char cThreadName[32] = {0}; prctl(PR_GET_NAME, (unsigned l ...
- C Primer Plus学习笔记(二)
1. C的左值用是指用于标志一个特定的数据对象的名字或表达式.“数据对象”是泛指数据存储的术语. 赋值运算符的左边应该是以个可以修改的左值. 右值是指可赋给可修gia的左值的量.右值可以是常量.变量或 ...
- 如何向VS2010中插入ActiveX控件并且附带相应的类
上两篇文章中我们已经讲述了ActiveX控件的一些相关知识,本文中,简单说明一下如何在我们自己的程序中使用ActiveX控件.(仍以我们上节课的例子为例) 我们打开VS2010编辑器,新建一个基于对话 ...
- iTween基础之Color(变换颜色)
一.基础介绍:二.基础属性 原文地址: http://blog.csdn.net/dingkun520wy/article/details/51065275 一.基础介绍 ColorTo:从当前颜色变 ...