问覆盖两次以上的面积
在求覆盖面积的基础上稍加改进
分情况讨论
1.cnt>1 : 说明该区间被覆盖两次或以上,那么长度就可以直接计算,就是该区间的长度
剩下的情况就是cnt=1或cnt=0
2.先看叶子节点,因为是叶子没有孩子了,所以被覆盖两次货以上的长度就是0(无论cnt=1或cnt=0都是0,因为是叶子。。。)
3.不是叶子节点 ,且cnt=1.注意这里,cnt=1确切的意义是什么,应该是,可以确定,这个区间被完全覆盖了1次,而有没有被完全覆盖两次或以上则不知道无法确定,那么怎么怎么办了,只要加上t[lch].s + t[rch].s 即,看看左右孩子区间被覆盖了一次或以上的长度,那么叠加在双亲上就是双亲被覆盖两次或以上的长度
3.不是叶子节点,且cnt=0,确切的意义应该是不完全不知道被覆盖的情况(不知道有没有被覆盖,被覆盖了几次,长度是多少都不知道),这种情况,只能由其左右孩子的信息所得
t[lch].ss + t[rch].ss , 即直接将左右孩子给覆盖了两次或以上的长度加起来,这样才能做到不重不漏
这里讲的很详细
http://www.cnblogs.com/scau20110726/archive/2013/04/14/3020998.html
代码:
//
// main.cpp
// wall
//
// Created by Mr.Xue on 17/7/20.
// Copyright © 2017年 Mr.Xue. All rights reserved.
//
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
struct node
{
double l,r,h;
int f;
}a[5000];
struct nodee
{
double s,ss;
int cnt;
}t[5000];
double has[5000];
bool cmp(node x,node y)
{
return x.h<y.h;
}
void build(int l,int r,int n)
{
t[n].ss=0;
t[n].s=0;
t[n].cnt=0;
if(l==r)
return;
int mid=(l+r)/2;
build(l,mid,n*2);
build(mid+1,r,n*2+1);
}
int find(double x,int l,int r)//二分查找在has中的编号
{
while(l<=r)
{
int mid=(l+r)/2;
if(has[mid]==x)
return mid;
if(has[mid]<x)
l=mid+1;
else
r=mid-1;
}
return -1;
}
void pushup(int k,int l,int r)//用来跟新sum
{
if(t[k].cnt)//编号为k的整个范围都可以算面积,直接has[r+1]-has[l]
t[k].s=has[r+1]-has[l];
else if(l==r)//到了叶子节点
t[k].s=0;
else//不是叶子节点
t[k].s=t[k*2+1].s+t[k*2].s;
if(t[k].cnt>1)
t[k].ss=has[r+1]-has[l];
else if(l==r)
t[k].ss=0;
else if(t[k].cnt==1)
t[k].ss=t[k*2].s+t[k*2+1].s;
else
t[k].ss=t[k*2].ss+t[k*2+1].ss;
}
void updata(int k,int l,int r,int x,int y,int flag)//用来查找和跟新
{
if(l==x&&r==y)
{
t[k].cnt+=flag;
pushup(k,l,r);
return;
}
int mid=(l+r)/2;
if(mid>=y)
updata(k*2,l,mid,x,y,flag);
else if(mid<x)
updata(k*2+1,mid+1,r,x,y,flag);
else
{
updata(k*2,l,mid,x,mid,flag);
updata(k*2+1,mid+1,r,mid+1,y,flag);
}
pushup(k,l,r);
}
int main()
{
int n;
double x1,y1,x2,y2;
double ans;
int test;
scanf("%d",&test);
while(test--)
{
scanf("%d",&n);
memset(t,0,sizeof(t));
//memset(sum,0,sizeof(sum));
ans=0.0;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a[i*2].l=x1+1;
a[i*2].r=x2+1;
a[i*2].h=y2+1;
a[i*2].f=-1;
has[i*2]=x2+1;
a[2*i-1].l=x1+1;
a[i*2-1].r=x2+1;
a[i*2-1].h=y1+1;
a[i*2-1].f=1;
has[i*2-1]=x1+1;
}
sort(has+1,has+2*n+1);
sort(a+1,a+1+2*n,cmp);
int m=1;
for(int i=1; i<=n*2; i++)
if(has[i]!=has[i-1])
has[m++]=has[i];
build(1,m-1,1);
for(int i=1;i<=2*n;i++)
{
int l=find(a[i].l,1,m);
int r=find(a[i].r,1,m)-1;
if(l<=r)
updata(1,1,2*n,l,r,a[i].f);
ans+=t[1].ss*(a[i+1].h-a[i].h);
}
printf("%.2lf\n",ans);
}
return 0;
}