题目描述:
给定很多个矩形,给定方式是对角线坐标点.求面积的并。
大致思路:
扫描线+线段树;
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <stdlib.h>
#include <math.h>
#include <time.h>
using namespace std;
typedef long long int LL;
const int INF=2e9+1e8;
const int maxn=1e6+10;
struct Date
{
double l,r,high;
int flag;
} data[maxn];
double myh[maxn],input[maxn];
int n,k;
int getid(double x)
{
return lower_bound(myh+1,myh+k,x)-myh;
}
struct Seg
{
int l,r,val;
double res;
} Tree[maxn];
void build(int i,int l,int r)
{
Tree[i].l=l,Tree[i].r=r;
Tree[i].val=0,Tree[i].res=0;
if(l==r) return ;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}
void deal(int i)
{
if(Tree[i].val) Tree[i].res=myh[Tree[i].r+1]-myh[Tree[i].l];
else if(Tree[i].l==Tree[i].r) Tree[i].res=0.;
else Tree[i].res=Tree[i<<1].res+Tree[i<<1|1].res;
}
void update(int i,int l,int r,int x)
{
if(l>r) return ;
if(Tree[i].l==l&&Tree[i].r==r)
{
Tree[i].val+=x;
deal(i);
return ;
}
int mid=(Tree[i].l+Tree[i].r)>>1;
if(r<=mid) update(i<<1,l,r,x);
else if(l>mid) update(i<<1|1,l,r,x);
else update(i<<1,l,mid,x),update(i<<1|1,mid+1,r,x);
deal(i);
}
double solve()
{
double ans=0;
update(1,getid(data[0].l),getid(data[0].r)-1,1);
for(int i=1; i<2*n; i++)
{
ans+=Tree[1].res*(data[i].high-data[i-1].high);
update(1,getid(data[i].l),getid(data[i].r)-1,data[i].flag);
}
return ans;
}
bool cmp(Date a,Date b)
{
return a.high<b.high;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
if(n==0) return 0;
for(int i=0; i<n; i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
data[i].l=x1,data[i].r=x2,data[i].high=y1,data[i].flag=1;
data[n+i].l=x1,data[i+n].r=x2,data[n+i].high=y2,data[i+n].flag=-1;
input[i]=x1,input[i+n]=x2;
}
sort(data,data+2*n,cmp);
sort(input,input+2*n);
k=1;
myh[k++]=input[0];
for(int i=1; i<2*n; i++)
if(input[i]!=input[i-1]) myh[k++]=input[i];
build(1,1,k-1);
printf("%.2lf\n",solve());
}
return 0;
}