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 ...
随机推荐
- NOJ1008-第几天
第几天 时间限制(普通/Java) : 1000 MS/ 3000 MS 运行内存限制 : 65536 KByte总提交 : 2701 测试通过 : 800 ...
- hdu1007
Have you ever played quoit in a playground? Quoit is a game in which flat rings are pitched at some ...
- 误删system04.dbf 报:ORA-01157 ORA-01110
DB:Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production OS:Oracle Linux 5.7 ...
- 快速的搭建JFinal的ORM框架示例
JFinal默认用的是Freemarker作为视图. 所以,打架还是准备好俩个jar包吧! freemarker-2.3.16.jar JFinal-bin-1.5.jar 新建web工程和添加lib ...
- iOS项目开发中的目录结构
目录结构: 1.AppDelegate 这个目录下放的是AppDelegate.h(.m)文件,是整个应用的入口文件,所以单独拿出来. 2.Models 这个目录下放一些与数据相关的Mod ...
- mysql开启日志
在 centos 5 下, 在 mysld 下面,添加一行 log=/var/log/mysql.log 然后执行如下命令 touch /var/log/mysql.logchmod 777 /va ...
- UITextField的常用属性,Delegate,重绘
一 属性 UITextField * myTextField = [[UITextField alloc] initWithFrame:CGRectMake(50, 100, 200, 50 ...
- 安装ubuntu时将boot目录单独挂载的意义
只有一个意义那就是当你的情况是:单个硬盘里面安装多个系统. 如果不是这样,就别动它.
- 基于.net mvc的校友录(三、实体模型实现)
实体模型设计 由于是实际开发,而且是时间比较紧的,所以,在开发实现过程中,总有一些对原计划的改动: AlumniBookModel数据库实体模型 这是主数据实体类,EF会根据此实体生成数据库,它的每一 ...
- SpringMVC核心类DispatcherServlet
配置DispatcherServlet 要使用SpringMVC,必须在web.xml中配置好这个DispatcherServlet类 <!-- spring框架必须定义ContextLoade ...