http://acm.hdu.edu.cn/showproblem.php?pid=1255
分析:
和求面积并类似 面积并的时候我们只要求出覆盖一次的长度就行 而这里要求出覆盖两次及其以上的长度 分以下情况讨论
1、标记s>=2 覆盖大于等于两次 len1、len2直接求就是了
2、标记s==0 len1、len2都要从左右子区间求解(若为叶子节点 len2为0 覆盖两次是不可能的)
3、标记s==1 len1直接求就是了 若为叶子节点 len2同样为0 如果不是叶子节点 看左右子区间如果有被覆盖过一次的加上这次覆盖 就是两次了
AC代码:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include<list>
#include <bitset>
#include <climits>
#include <algorithm>
#define gcd(a,b) __gcd(a,b)
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w",stdout)
typedef long long LL;
const LL mod=1e9+7;
const int INF=0x3f3f3f3f;
const int MAX=1e3+5;
const double PI=acos(-1.0);
using namespace std;
struct node{// 存储矩形边的信息
double x1,x2,h;
int flag;// 出边还是入边
}a[MAX];
struct Tree{
int l,r;
double len,len2;
int s;
}T[MAX];
double ls[MAX];// 离散化
bool cmp(node x,node y){
return x.h<y.h;
}
void pushUP(int rt){// 标记上推
if (T[rt].s>=2){// 覆盖大于等于两次
T[rt].len=T[rt].len2=ls[T[rt].r+1]-ls[T[rt].l];
}
else if (T[rt].s==1){
T[rt].len=ls[T[rt].r+1]-ls[T[rt].l];
if (T[rt].l==T[rt].r) T[rt].len2=0;
else T[rt].len2=T[rt*2].len+T[rt*2+1].len;
}
else {
if (T[rt].l==T[rt].r) T[rt].len2=T[rt].len=0;
else{
T[rt].len=T[rt*2].len+T[rt*2+1].len;
T[rt].len2=T[rt*2].len2+T[rt*2+1].len2;
}
}
}
void build(int rt,int l,int r){// 建树
T[rt].s=0;T[rt].len2=0;T[rt].len=0;
T[rt].l=l;T[rt].r=r;
if (l==r) return ;
int mid=(l+r)/2;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
}
void update(int rt,int l,int r,int e){// 修改区间
if (T[rt].l>=l&&T[rt].r<=r){
T[rt].s+=e;
pushUP(rt);
return ;
}
int mid=(T[rt].l+T[rt].r)/2;
if (r<=mid) update(rt*2,l,r,e);// 如果在左侧左侧更新
else if (l>mid) update(rt*2+1,l,r,e);// 如果在右侧右侧更新
else{// 两侧都更新
update(rt*2,l,mid,e);
update(rt*2+1,mid+1,r,e);
}
pushUP(rt);
}
int main (){
int t;
//FIN;
scanf ("%d",&t);
while (t--){
int len=0,n;
scanf ("%d",&n);
for (int i=0;i<n;i++){
double x1,y1,x2,y2;
scanf ("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a[len].x1=x1;a[len].x2=x2;a[len].h=y1;
a[len].flag=1;ls[len]=x1;len++;
a[len].x1=x1;a[len].x2=x2;a[len].h=y2;
a[len].flag=-1;ls[len]=x2;len++;
}
sort(ls,ls+len);
sort(a,a+len,cmp);
len=unique(ls,ls+len)-ls;// 去重
build(1,0,len-1);
double ans=0;
for (int i=0;i<2*n;i++){
int l=lower_bound(ls,ls+len,a[i].x1)-ls;
int r=lower_bound(ls,ls+len,a[i].x2)-ls-1;
update(1,l,r,a[i].flag);
ans+=T[1].len2*(a[i+1].h-a[i].h);
}
printf("%.2f\n",ans);
}
}