「Hdu 1542」Atlantis (线段树 + 扫描线)

Hdu 1542
线段树离散化以后进行扫描线求面积并。

具体就是用一条平行于$y$轴的直线自左向右地扫过去,然后每次扫到一个整块长方形记录面积。
记录方法是,一个矩形分成左右两个边,左边在线段树中增加,右边在线段树中减少。则当前线段树中的所有大于0的数的个数即为当前长方形的一边。另一边为当前边横坐标减去前一条边的横坐标。

需要离散化。

这里维护的线段树很特殊,只需要查询根节点的和,则在线段树直接维护离散前的数据长度,记录一下区间覆盖次数,大于0则有值,否则没有。注意线段树里面每个点维护的是第几段的覆盖次数。

http://www.cnblogs.com/scau20110726/archive/2013/03/21/2972808.html

2018/12/25 重写

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<set>
#include<queue>
#include<cmath>
#define ms(i, j) memset(i, j, sizeof i)
#define LL long long
#define db double
#define fir first
#define sec second
#define mp make_pair
using namespace std;
int kse = 0;
namespace flyinthesky {
const int MAXN = 500 + 5;
struct data {
int ymin, ymax, v;
db x, fymin, fymax;
bool operator < (const data &rhs) const {return x < rhs.x;}
} cz[1000];
int n, cnt, czcnt, minpos;
db whw[1000], ans;
#define lc (o << 1)
#define rc (o << 1 | 1)
#define M ((l + r) >> 1)
db sumv[MAXN * 4];
int lazy[MAXN * 4];
void pushup(int o, int l, int r) {
if (lazy[o]) {
sumv[o] = whw[r + 1] - whw[l];
} else sumv[o] = sumv[lc] + sumv[rc];
}
void update(int o, int l, int r, int x, int y, int v) {
if (x <= l && r <= y) {
lazy[o] += v;
if (lazy[o] > 0) sumv[o] = whw[r + 1] - whw[l]; else sumv[o] = sumv[lc] + sumv[rc];
return ;
}
if (x <= M) update(lc, l, M, x, y, v);
if (M < y) update(rc, M + 1, r, x, y, v);
pushup(o, l, r);
}
void clean() {
ms(sumv, 0), ms(lazy, 0), ans = 0.0, czcnt = cnt = 0;
}
int solve() {
clean();
for (int i = 1; i <= n; ++i) {
db x1, y1, x2, y2;
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
cz[++czcnt] = (data){0, 0, 1, x1, y1, y2};
cz[++czcnt] = (data){0, 0, -1, x2, y1, y2};
whw[++cnt] = y1, whw[++cnt] = y2;
}
sort(whw + 1, whw + 1 + cnt), cnt = unique(whw + 1, whw + 1 + cnt) - whw - 1;
for (int i = 1; i <= czcnt; ++i) cz[i].ymin = lower_bound(whw + 1, whw + 1 + cnt, cz[i].fymin) - whw - 1, cz[i].ymax = lower_bound(whw + 1, whw + 1 + cnt, cz[i].fymax) - whw - 1;
// for (int i = 1; i <= czcnt; ++i) printf("cz %d: x=%.2lf, ymin=%.2lf, ymax=%.2lf, opt=%d\n", i, cz[i].x, cz[i].fymin, cz[i].fymax, cz[i].v);
// for (int i = 1; i <= czcnt; ++i) printf("cz %d: x=%.2lf, ymin=%d, ymax=%d, opt=%d\n", i, cz[i].x, cz[i].ymin, cz[i].ymax, cz[i].v);
sort(cz + 1, cz + 1 + czcnt);
cz[0] = (data){-1, -1, 0, 0, 0, 0};
for (int i = 1; i <= czcnt; ++i) {
ans += sumv[1] * (cz[i].x - cz[i - 1].x);
if (cz[i].ymin + 1 <= cz[i].ymax) update(1, 1, cnt, cz[i].ymin + 1, cz[i].ymax, cz[i].v);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", ++kse, ans);
return 0;
}
}
int main() {
while (scanf("%d", &flyinthesky::n) == 1 && flyinthesky::n) flyinthesky::solve();
return 0;
}

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define ms(i,j) memset(i,j, sizeof i);
using namespace std;
const int MAXN = 100 + 5;
struct xian
{
int f; //up or down, up is -1, down is 1
double l, r;//the interval's end points
double h;//height
bool operator < (const xian &b) const
{
return h<b.h;
}
}a[MAXN*2];
double hashs[MAXN*2];//the hashsed points
int n;
#define lc o*2
#define rc o*2+1
#define M (l+r)/2
struct st
{
int col[MAXN*4*4];//col[i]>0 means this inerval was full marked
double sum[MAXN*4*4];//available room
void pushup(int o, int l, int r)
{
if (col[o]>0)
{
sum[o] = hashs[r+1]-hashs[l];
} else if (l==r) sum[o] = 0;
else {
sum[o] = sum[lc] + sum[rc];
}
}
void update(int o, int l ,int r, int x, int y, int c)
{
if (x<=l&&r<=y)
{
col[o] += c;
pushup(o,l,r);
return ;
}
if (x<=M) update(lc,l,M,x,y,c);
if (M<y) update(rc,M+1,r,x,y,c);
pushup(o,l,r);
}
}tree;
//binary-search the elements in hashs[]
int find(int x, int y, double v)
{
int l = x, r = y, mid;
while (l<r)
{
mid = (l+r)/2;
if (v>hashs[mid])
{
l = mid+1;
} else r = mid;
}
return r;
}
int main()
{
int kase = 0;
while (scanf("%d", &n)==1&&n)
{
kase++;
for (int i=0;i<n;i++)
{
double x1, y1, x2, y2;
scanf("%lf%lf%lf%lf", &x1,&y1,&x2,&y2);
a[i*2].f = 1; a[i*2+1].f = -1;
a[i*2].l = x1; a[i*2+1].l = x1;
a[i*2].r = x2; a[i*2+1].r = x2;
a[i*2].h = y1; a[i*2+1].h = y2;//add xian
hashs[i*2] = x1; hashs[i*2+1] = x2;//add hashs
}
sort(hashs, hashs+2*n); sort(a, a+2*n); //sort to hashs
//delete the repeated elements
int m = 1;
for (int i=1;i<2*n;i++)
if (hashs[i]!=hashs[i-1]) hashs[m++] = hashs[i];
//produce
ms(tree.col, 0);
double ans = 0;
for (int i=0;i<n*2;i++)
{
int l = find(0, m, a[i].l);
int r = find(0, m, a[i].r)-1;
/*int l = lower_bound(hashs, hashs+m, a[i].l)-hashs;
int r = lower_bound(hashs, hashs+m, a[i].r)-hashs-1;*/
if (r>=l) tree.update(1,0,m-2,l,r,a[i].f);//一定要r>=l,这里原来错了
ans += (a[i+1].h-a[i].h)*tree.sum[1];
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", kase, ans);
}
return 0;
}
------ 本文结束 ------