当前位置: 代码迷 >> 综合 >> HDU 1542:Atlantis(线段树+扫描线+离散化)
  详细解决方案

HDU 1542:Atlantis(线段树+扫描线+离散化)

热度:97   发布时间:2023-12-01 21:54:14.0

线段树+扫描线+离散化模板题目
第一次做这种类型的题目,以前以为比较难,就没敢碰它,现在学起来感觉还挺简单的,对于我来说,这种离散化思想要稍微难理解一点,其他的部分挺简单的
又学到了新东西!!!

参考博客:线段树 + 扫描线加深详解

详细请看代码:

#include<cstdio>
#include<algorithm>
using namespace std;const int maxn=220;struct Node{double l,r;double h;int type;Node(double l_=0,double r_=0,double h_=0,int type_=0):l(l_),r(r_),h(h_),type(type_){}
}node[maxn];
double x[maxn];
int tot;double tree[maxn<<2];
int cnt[maxn<<2];inline bool cmp(Node a,Node b){return a.h<b.h;
}inline int getX_Ind(double locate){int l=1;int r=tot;while(l<=r){int mid=(l+r)>>1;if(x[mid]==locate) return mid;if(x[mid]<locate) l=mid+1;else r=mid-1; }
}inline void PushUp(int root,int l,int r){if(cnt[root]) tree[root]=x[r+1]-x[l];else if(l==r) tree[root]=0;else tree[root]=tree[root<<1]+tree[root<<1|1];
}inline void Update(int root,int l,int r,int L,int R,int v){if(L<=l && R>=r){cnt[root]+=v;PushUp(root,l,r);return ;}int mid=(l+r)>>1;if(R<=mid) Update(root<<1,l,mid,L,R,v);else if(L>mid) Update(root<<1|1,mid+1,r,L,R,v);else Update(root<<1,l,mid,L,R,v),Update(root<<1|1,mid+1,r,L,R,v);PushUp(root,l,r);
}int main(){int n,m;int C=0;while(scanf("%d",&n)==1&&n){m=2*n;for(int i=0;i<n;i++){double x1,y1,x2,y2;scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);int l=i*2+1;int r=i*2+2;node[l]=Node(x1,x2,y1,1);x[l]=x1;node[r]=Node(x1,x2,y2,-1);x[r]=x2;}sort(x+1,x+m+1);sort(node+1,node+m+1,cmp);tot=1;double area=0;for(int i=2;i<=m;i++) if(x[i]!=x[i-1]) x[++tot]=x[i];for(int i=1;i<=m;i++){int L=getX_Ind(node[i].l);int R=getX_Ind(node[i].r)-1;Update(1,1,tot,L,R,node[i].type);if(i!=m) area+=tree[1]*(node[i+1].h-node[i].h);}printf("Test case #%d\nTotal explored area: %.2f\n\n",++C,area);}
}