2 10 10 20 20 15 15 25 25.5 0
Test case #1 Total explored area: 180.00所谓的离散化,大家可以简单的理解为,将一组很大的数据,浓缩为一组很小的数据,用这组数据来代替原数据的作用,比如给你1000个数,数的范围为(1,1e18)我们这里就可以用离散化,由于只有1000个数,我们可以用一个数组的下标代表提供的每一数,如果需要这个数据了,由于是下标,可以直接通过下标获得,如此就是离散化。讲得很基础,是个很不错的博客然后提醒一下这个扫描线要注意的问题就是区间的问题一般的线段树以及我们的区间修改合并,都有一个共同点,就是不会出现区间缺失的现象,什么叫区间缺失,顾名思义,区间缺失就是缺少一些区间没有进行运算,这里的扫描线就会遇到这个问题。普遍的,我们的线段树以及数据区间分布是这样的:[1, a][a + 1, b][b + 1, c][c + 1, d][d + 1, e].......但是如果只是简简单单的用这个来解决扫描线的问题会导致错误,为什么因为,他没有涉及到[a,a + 1],在扫描线中会出现[a,a + 1]中的数据,而常用的线段树的区间概念是无法解决这样的问题的,出现了所谓的区间缺失,怎样解决,下面的代码给出了解决方案,这里简单的提一下,就是利用[ , ),这个区间性质,左闭右开,即可解决区间缺失问题#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <queue> using namespace std; typedef long long LL; #define lson rt << 1, l, mid #define rson rt << 1|1, mid + 1, r const int MAXN = 2000 + 5; int Col[MAXN << 2], n, cnt, res; double X[MAXN << 2], Sum[MAXN << 2]; struct seg { double l,r,h; int s; seg() {} seg(double l,double r,double h,int s):l(l),r(r),h(h),s(s) {} bool operator < (const seg & object) const { return h < object.h; } } S[MAXN]; void pushup(int rt,int l,int r) { if (Col[rt]) Sum[rt] = X[r+1] - X[l];//利用[ , ),这个区间性质,左闭右开 else if (l == r) Sum[rt] = 0; else Sum[rt] = Sum[rt<<1] + Sum[rt<<1|1]; } void update(int L, int R, int c,int rt,int l, int r) { if(L <= l && r <= R) { Col[rt] += c; pushup(rt,l,r); return ; } int mid = (l + r) >> 1; if(L <= mid) update(L, R, c, lson); if(R > mid) update(L, R, c, rson); pushup(rt,l,r); } int binary_find(double x){ int lb = -1,ub = res - 1; while(ub - lb > 1){ int mid = (lb + ub) >> 1; if(X[mid] >= x) ub = mid; else lb = mid; } return ub; } int main() { int cas = 1; while(~ scanf("%d", &n), n) { cnt = res = 0; for(int i = 0 ; i < n; i ++) { double a,b,c,d; scanf("%lf%lf%lf%lf",&a, &b, &c,&d); S[cnt] = seg(a, c, b, 1); X[cnt ++] = a; S[cnt] = seg(a, c, d, -1); X[cnt ++] = c; } sort(X, X + cnt); sort(S, S + cnt); res ++; for(int i = 1; i < cnt; i ++) { if(X[i] != X[i - 1]) X[res ++] = X[i]; } memset(Sum, 0, sizeof(Sum)); memset(Col, 0, sizeof(Col)); double ans = 0; for(int i = 0;i < cnt - 1;i ++){ int l = binary_find(S[i].l); int r = binary_find(S[i].r) - 1;//利用[ , ),这个区间性质,左闭右开 update(l, r, S[i].s, 1, 0, res - 1); ans += Sum[1] * (S[i + 1].h - S[i].h); } printf("Test case #%d\nTotal explored area: %.2lf\n\n",cas++ , ans); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
原文:http://blog.csdn.net/qq_18661257/article/details/47622677