首先推荐一篇大佬的博客:https://blog.csdn.net/xianpingping/article/details/83032798
题目:http://poj.org/problem?id=1151
扫描线裸题,主要是为了贴个板子
Ac code:
#include<stack>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
#include<cstring>
using namespace std;
const int maxn=220;
struct Node{
double l,r,h;
int f;
Node() {}
Node(double a,double b,double c,int d):l(a),r(b),h(c),f(d) {}
bool operator < (const Node& cmp) const
{
return h<cmp.h;
}
}node[maxn];
struct node
{
int cnt;
double len;
} tree[maxn<<2];
double X[maxn<<1];
void pushdown(int l,int r,int rt)
{
if(tree[rt].cnt)//当前的边被标记,就把当前的长度加上
tree[rt].len=X[r+1]-X[l];///还原r
else if(l==r)//当为一个点的时候长度为0
tree[rt].len=0;
else//其他情况把左右两个区间的值加上
tree[rt].len=tree[rt<<1].len+tree[rt<<1|1].len;
}
void update(int L,int R,int l,int r,int rt,int val)
{
if(L<=l&&r<=R)
{
tree[rt].cnt+=val;//加上标记的值
pushdown(l,r,rt);//像下更新节点
return;
}
int m=(l+r)>>1;
if(L<=m) update(L,R,l,m,rt<<1,val);
if(R>m) update(L,R,m+1,r,rt<<1|1,val);
pushdown(l,r,rt);
}
int main()
{
int n,cas=0;
double x1,x2,y1,y2;
while(scanf("%d",&n)!=EOF&&n)
{
memset(tree,0,sizeof tree);
int num=0;
for(int i=1; i<=n; i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
X[num]=x1;
node[num++]=Node(x1,x2,y1,1);
X[num]=x2;
node[num++]=Node(x1,x2,y2,-1);
}
sort(node,node+num);
sort(X,X+num);
int m=unique(X,X+num)-X;
double ans=0;
for(int i=0;i<num;i++)
{
int l=lower_bound(X,X+m,node[i].l)-X;
int r=lower_bound(X,X+m,node[i].r)-X-1;///-1是为了计算[mid,mid+1]的长度,按照普通线段树求法,[mid,mid+1]的长度会丢失
update(l,r,0,m,1,node[i].f);
ans+=tree[1].len*(node[i+1].h-node[i].h);
}
printf("Test case #%d\nTotal explored area: %.2f\n\n",++cas,ans);
}
return 0;
}