(磨人的小妖精)hdu 1542 Atlantis:线段树扫描线,离散化
2016-07-24 21:40
447 查看
http://acm.hdu.edu.cn/showproblem.php?pid=1542
啊~~~~~做完这道题感觉智商被掏空!!!!!
1,首先由于横纵坐标不一定是整数,需要根据实际的数据进行离散化;
2,由于我的扫描是从下往上的,所以将横坐标进行离散化;
3,从下到上进行扫描的时候,当遇到一条底边则将覆盖数目加一,否则减一;
4,每次枚举每一条边,累加将前后两条边的高度差乘以区间覆盖长度;
啊~~~~~做完这道题感觉智商被掏空!!!!!
1,首先由于横纵坐标不一定是整数,需要根据实际的数据进行离散化;
2,由于我的扫描是从下往上的,所以将横坐标进行离散化;
3,从下到上进行扫描的时候,当遇到一条底边则将覆盖数目加一,否则减一;
4,每次枚举每一条边,累加将前后两条边的高度差乘以区间覆盖长度;
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxn=1009; double pos[maxn*2];//保留离散化的结果 struct line { double l,r,h; int f;//标记是上面(1)的边还是下面的边(-1) } seg[maxn<<1]; struct node { int l,r,cnt; double len; } ac[maxn<<3]; int cmp(line a,line b) { return a.h<b.h;//按照线段按高度排序 } void build(int l,int r,int rt)//build维护的是一个闭区间 { ac[rt].l=l,ac[rt].r=r,ac[rt].len=ac[rt].cnt=0; if(l==r) return; int m=ac[rt].l+ac[rt].r>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } void pushup(int rt)//为什么要加一呢,因为build 维护的是闭区间!而更新的时候我们更新的是一个左闭右开的区间 { if(ac[rt].cnt) ac[rt].len=pos[ac[rt].r+1]-pos[ac[rt].l];//cnt不为零则全部被覆盖 else if(ac[rt].l==ac[rt].r) ac[rt].len=0;//此时已不再是线段 else ac[rt].len=ac[rt<<1].len+ac[rt<<1|1].len;//如果区间覆盖不连续,则从子区间找值 } int fin(double key,int low,int high)//找出离散化后的位置 { while(low<=high) { int mid=high+low>>1; if(pos[mid]==key) return mid; else if(pos[mid]<key) low=mid+1; else high=mid-1; } return -1; } void update(int l,int r,int val,int rt) { if(l<=ac[rt].l&&r>=ac[rt].r) { ac[rt].cnt+=val; pushup(rt); return; } int m=ac[rt].l+ac[rt].r>>1; if(m>=r) update(l,r,val,rt<<1); else if(m<l) update(l,r,val,rt<<1|1); else { update(l,r,val,rt<<1); update(l,r,val,rt<<1|1); } pushup(rt); } int main() { int ase=1; int n; while(scanf("%d",&n)&&n) { double x1,x2,y1,y2; int m=0; for(int i=0; i<n; i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); seg[m].l=x1,seg[m].r=x2,seg[m].h=y1,seg[m].f=1;//遇到下面的边则加一 seg[m+1].l=x1,seg[m+1].r=x2,seg[m+1].h=y2,seg[m+1].f=-1;//遇到上面的边则减一 pos[m]=x1,pos[m+1]=x2; m+=2; } sort(seg,seg+m,cmp); sort(pos,pos+m); int cnt=1; for(int i=1; i<m; i++)//离散化后去重 if(pos[i]!=pos[i-1]) pos[cnt++]=pos[i]; build(0,cnt-1,1); double ans=0; for(int i=0; i<m; i++) { int left=fin(seg[i].l,0,cnt-1); int right=fin(seg[i].r,0,cnt-1)-1;//要减一 update(left,right,seg[i].f,1); ans+=(seg[i+1].h-seg[i].h)*ac[1].len; } printf("Test case #%d\n",ase++); printf("Total explored area: %.2f\n\n",ans); } return 0; }
相关文章推荐
- POJ 1222 EXTENDED LIGHTS OUT熄灯游戏
- 如何创建BFC
- 软技能-John
- C#基础知识(七)——方法重载与out、ref、params参数
- 单态模式
- RDD Transformation —— sample
- bash 基本技巧
- 暑假网页学习1(浮动问题)
- 1、什么是BFC
- javaweb总结
- PostGIS
- 不要在setTimeout中使用字符串
- 《JavaScript高级程序设计》 - 读书笔记 - 第4章 变量、作用域和内存问题
- 插入排序算法之移动交换法
- Node.js+npm安装
- MySQL数据库学习笔记(三)----基本的SQL语句
- Django集成的子框架
- php设计模式之简单工厂模式
- java设计模式——多例模式
- 枚举