求n个矩形的面积并。
看了一下扫描线,这个东西和某场BC的贪心题目类似,就是一个矩形拆成两个线段,标记一下矩形开始的线段和结束的线段,那么这个矩形的面积就是两条线段所在的坐标差*线段长度..就是线段树建立方式和普通的有点差别...[l,r]拆分成两个区间的时候要一个拆成[l,mid],另外一个不是[mid+1,r]而是[mid,r]..然后多加一个push_up可以省好多事...
弱的线段树扫描线代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<set>
#include<vector>
#include<iterator>
#include<map>
using namespace std;
#define LL long long
vector<double> v;
vector<double>::iterator it1;
struct node
{
int l,r,cover;
double len;
}data[20000];
struct lin
{
double yu,yd,x;
int cover;
}line[20000];
int cmp(lin a,lin b)
{
return a.x<b.x;
}
void build(int l,int r,int k)
{
data[k].l=l;
data[k].r=r;
data[k].len=0;
data[k].cover=0;
if(l+1==r)
return ;
int mid=(l+r)/2;
build(l,mid,k*2);
build(mid,r,k*2+1);
}
void push_up(int k)
{
if(data[k].cover)
data[k].len=v[data[k].r]-v[data[k].l];
else if(data[k].l+1==data[k].r)
data[k].len=0;
else
data[k].len=data[k*2].len+data[k*2+1].len;
}
void updata(int l,int r,int k,int x)
{
if(data[k].l>r || data[k].r<l)
return;
if(data[k].l>=l&&data[k].r<=r)
{
data[k].cover+=x;
push_up(k);
return ;
}
updata(l,r,k*2,x);
updata(l,r,k*2+1,x);
push_up(k);
}
int main()
{
int n;
int cas=1;
while(scanf("%d",&n),n)
{
v.clear();
v.push_back(-1);
int m=0;
double x1,x2,y1,y2;
for(int i=0;i<n;i++)
{
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
v.push_back(y1);
line[m].cover=1;
line[m].yd=y1;
line[m].yu=y2;
line[m].x=x1;
m++;
v.push_back(y2);
line[m].cover=-1;
line[m].yd=y1;
line[m].yu=y2;
line[m].x=x2;
m++;
}
sort(v.begin(),v.end());
it1=unique(v.begin(),v.end());
v.erase(it1,v.end());
int k=v.size();
build(1,k-1,1);
sort(line,line+m,cmp);
double ans=0;
printf("Test case #%d\n",cas++);
for(int i=0;i<m-1;i++)
{
int x=lower_bound(v.begin(),v.end(),line[i].yd)-v.begin();
int y=lower_bound(v.begin(),v.end(),line[i].yu)-v.begin();
updata(x,y,1,line[i].cover);
ans+=data[1].len*(line[i+1].x-line[i].x);
}
printf("Total explored area: %0.2f\n\n",ans);
}
return 0;
}