第一次做扫描线,这个是矩形面积并。。。。wa了好多发,才发现本应是double的数组写成了int。。。。
HH神总结的线段树专辑:https://wenku.baidu.com/view/71fc1659ba1aa8114431d97b.html
里面的例题。。。。
思路:浮点数先要离散化;然后把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用 cnt 表示该区间下边比上边多几个。比如cnt[i]=0,说明节点i所管理的区间没有被线段覆盖。。。
线段树的每个叶节点表示一条线段,不是一个点
用结构体保存线段,每条线段有两个端点的x坐标和线段的高度(y坐标)和一个标记s组成,s为1表示这条线段是矩形中下边的那条线段,s为-1表示为上边的那条线段,其余的写在图片和代码中。。。
#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct Line
{
double l,r,h;
int s;
Line(){}
Line(double a, double b, double c, int d):l(a),r(b),h(c),s(d){}
bool operator < (const Line& b) const
{
return h < b.h;
}
};
const int MAXN = 2222;
Line lines[MAXN];
double x[MAXN];
int cnt[MAXN<<2];
double sum[MAXN<<2];
int binS(int n, double val)
{
int lb = 0;
int ub = n-1;
while(lb <= ub)
{
int mid = (lb+ub) >> 1;
if(x[mid] > val) ub = mid-1;
else if(x[mid] < val) lb = mid+1;
else return mid;
}
return -1;
}
void pushUp(int l, int r, int rt)
{
//区间完全被覆盖
if(cnt[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 l, int r, int rt)
{
if(l >= L && r <= R)
{
cnt[rt] += c;
pushUp(l,r,rt);//计算当前节点覆盖的长度
return;
}
int m = (l+r) >> 1;
if(L <= m) update(L,R,c,lson);
if(R > m) update(L,R,c,rson);
pushUp(l,r,rt);
}
int main()
{
ios::sync_with_stdio(false);
int n,m,time = 0;
double a,b,c,d;
while(cin >> n && n)
{
m = 0;
for(int i = 0; i < n; ++i)
{
cin >> a >> b >> c >> d;
x[m] = a;
lines[m++] = Line(a,c,b,1);
x[m] = c;
lines[m++] = Line(a,c,d,-1);
}
sort(x,x+m);
sort(lines,lines+m);
int k = unique(x,x+m) - x;
double res = 0;
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
for(int i = 0; i < m-1; ++i)
{
//l表示是从左边数第几个线段
int l = binS(k,lines[i].l);
//binS(k,lines[i].r)表示的是线段右边的点,-1表示的就是这是第几条线段
int r = binS(k,lines[i].r)-1;
if(l <= r)
update(l,r,lines[i].s,0,k-1,1);
res += sum[1]*(lines[i+1].h-lines[i].h);
}
cout << "Test case #" << ++time << endl;
cout << fixed << setprecision(2) << "Total explored area: " << res << endl << endl;
}
return 0;
}