Atlantis poj1151 扫描线+线段树

时间:2022-05-12 22:11:54

Description


给定一些矩形的左下和右上坐标,求形成图形的总面积

Solution


嗯这道题按理说离散是可以艹过去的写的优美一些应该没问题毕竟n才100

于是我采用了扫描线的做法(滑稽

首先把x、y坐标分别离散,然后将横向的线段保存并按x坐标升序排序,这样我们得到的是2n条线段,为了区分我们把矩形的下部线段标为1,上部标为-1

接着就建一棵线段树,每次遇到下边就插入一段线段(连续+1),遇到上边就删除一条线段(连续-1),统计不为0的长度len与两线段间的距离h就是新增的面积

然后这道题的复杂度单点修改的线段树是可以艹过去的

还是不懂就看这里

Code


#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define fill(x, t) memset(x, t, sizeof(x))
#define db double
#define N 201
using namespace std;
struct treeNode{int l, r, c;}t[N * 5];
struct segement{db x; int l, r, c;}s[N];
struct data{db x; int index;}p[N];
int hy[N];
db lx[N], len;
inline void modify(int now, int l, int r, int v){
if (t[now].l + 1 == t[now].r){
t[now].c += v;
if (!t[now].c && v == -1){
len -= (lx[r] - lx[l]);
}else if (t[now].c == 1 && v == 1){
len += (lx[r] - lx[l]);
}
return;
}else{
int mid = (t[now].l + t[now].r) >> 1;
if (r <= mid){
modify(now * 2, l, r, v);
}else if (l >= mid){
modify(now * 2 + 1, l, r, v);
}else{
modify(now * 2, l, mid, v);
modify(now * 2 + 1, mid, r, v);
}
}
}
inline void build(int now, int l, int r){
t[now] = (treeNode){l, r, 0};
if (l + 1 == r){
return;
}
int mid = (l + r) >> 1;
build(now * 2, l, mid);
build(now * 2 + 1, mid, r);
}
inline int cmp1(data a, data b){
return a.x < b.x;
}
inline int cmp2(segement a, segement b){
return a.x < b.x;
}
int main(void){
int n, T = 0;
while (scanf("%d", &n) != EOF && n){
vector<data> v;
vector<segement> e;
rep(i, 1, n){
db u, l, d, r;
scanf("%lf%lf%lf%lf", &u, &l, &d, &r);
v.push_back((data){l, i * 2 - 1});
v.push_back((data){r, i * 2});
e.push_back((segement){u, i * 2 - 1, i * 2, 1});
e.push_back((segement){d, i * 2 - 1, i * 2, -1});
}
sort(v.begin(), v.end(), cmp1);
int cnt = 1;
hy[v[0].index] = cnt;
lx[1] = v[0].x;
rep(i, 1, v.size() - 1){
if (v[i].x != v[i - 1].x){
cnt += 1;
}
hy[v[i].index] = cnt;
lx[cnt] = v[i].x;
}
build(1, 1, cnt);
rep(i, 0, e.size() - 1){
e[i].l = hy[e[i].l];
e[i].r = hy[e[i].r];
}
sort(e.begin(), e.end(), cmp2);
rep(i, 0, e.size() - 1){
// printf("x = %.2f, l = %d, r = %d, c = %d\n", e[i].x, e[i].l, e[i].r, e[i].c);
}
len = 0;
db tot = 0;
rep(i, 0, e.size() - 2){
modify(1, e[i].l, e[i].r, e[i].c);
tot += (e[i + 1].x - e[i].x) * len;
}
printf("Test case #%d\nTotal explored area: %.2f\n\n", ++ T, tot);
}
return 0;
}