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 ...
随机推荐
- linux C socket
socket套接字和管道同样可以提供进程内通信.但套接字更胜一筹,不同的进程可以跨越不同的主机(说白了,支持网络通信).使用套接字的知名程序:telnet.rlogin.ftp等. 你需要知道的一些基 ...
- hdu 3172 Virtual Friends
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3172 并查集的运用... #include<algorithm> #include< ...
- scjp考试准备 - 1 - 循环控制
判断如下代码最后的执行结果. public class Breaker{ static String o = ""; public static void main(String[ ...
- FPGA---ucf文件编写
摘要:本文主要通过一个实例具体介绍ISE中通过编辑UCF文件来对FPGA设计进行约束,主要涉及到的约束包括时钟约束.群组约束.逻辑管脚约束以及物理属性约束. Xilinx FPGA设计约束的分类 Xi ...
- QWidget设置为模态问题
设置QWidget的Qt::WindowModality属性为Qt::WindowModal和Qt::ApplicationModal,发现窗体仍然不会模态,网上查了一下,有人说改属性只对window ...
- PB中掉用Run以后,等Run的程序关闭以后才会执行后边的语句
OleObject wsh integer li_rc CONSTANT integer MAXIMIZED = CONSTANT integer MINIMIZED = CONSTANT integ ...
- Linux 系统Telnet服务
Linux 系统Telnet服务 telnet与ssh相比,安全性能并不高,但是在ssh版本升级或者其他的情况下还是需要开启这一项服务.linux提供服务是由运行在后台的守护进程daemon来执行的, ...
- 使用C语言在Win控制台中输出带颜色的文字
学了这么久的C语言,一直停留在编写“控制台”程序的水平.黑色窗口,白色的文字,看多了着实让人感到枯燥无味.但是作为业余爱好者,我既没有那么多时间和精力去学习如何编写窗口程序,也没有那个必要一定用C去调 ...
- EF之外键Include() left join
项目中用EF实现外键查询出的数据, 查询数量正确, 但实现返回数据集数量不对 //DbContext.cs HasRequired(s => s.ClassRoom) .WithMany() . ...
- Differences Between Xcode Project Templates for iOS Apps
Differences Between Xcode Project Templates for iOS Apps When you create a new iOS app project in Xc ...