题目:
给出n个矩阵,求他们的面积并。
思路: 裸扫描线题,只要模板搞好,非常简单。要离散化x来缩小线段树的大小,剩下的就纯扫描线了。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1e5+10;
double xx[N<<1];
struct Edge
{
double l, r;
double h;
int inout;
Edge(){}
Edge(double left, double right, double height, double inou):l(left),r(right),h(height),inout(inou){}
}e[N<<1];
bool cmp(Edge a, Edge b)
{
return a.h<b.h;
}
struct Tree
{
int l, r;
int s;
double len;
int mid() {return (l+r)>>1;}
}tr[N<<2];
void pushup(int now)
{
if(tr[now].s) tr[now].len = xx[tr[now].r+1] - xx[tr[now].l];//这一步要+1,仔细看
else if(tr[now].l == tr[now].r) tr[now].len = 0;
else
tr[now].len = tr[now<<1].len + tr[now<<1|1].len;
}
void build(int now, int l, int r)
{
tr[now].l = l, tr[now].r = r;
tr[now].s = 0, tr[now].len = 0;
if(l == r) return ;
int mid = tr[now].mid();
build(now<<1, l, mid);
build(now<<1|1, mid+1, r);
}
void update(int now, int l, int r, int val)
{
if(tr[now].l >=l && tr[now].r<= r)
{
tr[now].s += val;
pushup(now);//这一步主要是有可能清零或者加一!!!!!!!!
return ;
}
int mid = tr[now].mid();
if(mid>=r) update(now<<1, l,r,val);
else if(mid<l)update(now<<1|1,l,r,val);
else
{
update(now<<1, l,mid,val);
update(now<<1|1, mid+1,r,val);
}
pushup(now);
}
int main()
{
int n,kas = 0;
int cnt;
while(scanf("%d", &n)&&n)
{
double x1, x2, y1,y2;
cnt = 0;
for(int i = 1;i<=n;i++)
{
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
xx[++cnt] = x1;
e[cnt] = Edge(x1, x2, y1, 1);
xx[++cnt] = x2;
e[cnt] = Edge(x1, x2, y2, -1);
}
sort(xx+1, xx+1+cnt);
sort(e+1, e+cnt+1, cmp);
int len = unique(xx+1, xx+cnt+1)-xx-1;
build(1, 1, len);
double ans = 0.0;
for(int i = 1;i<=cnt;i++)
{
int l = lower_bound(xx+1, xx+1+len,e[i].l)- xx;
int r = lower_bound(xx+1, xx+1+len, e[i].r)-xx-1;//这里也要特意减一!!!!!
update(1,l,r, e[i].inout);
ans+=tr[1].len* (e[i+1].h - e[i].h);
}
printf("Test case #%d\n",++kas);
printf("Total explored area: %.2f\n\n",ans);
}
return 0;
}