hdu1542 Atlantis
题意:矩形面积并
转自:http://www.notonlysuccess.com/index.php/segment-tree-complete/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1 //函数用左儿子
#define rson m+1,r,rt<<1|1 //函数用右儿子
#define havemid int m=(l+r)>>1 //取节点中点
#define left (rt<<1) //左儿子
#define right (rt<<1|1) //右儿子
const int maxn=210;
int cnt[maxn<<2]; //cnt表示该区间下面的边比上面的边多几个
double sum[maxn<<2]; //sum代表该区间内被覆盖的线段的长度总和
double X[maxn]; //离散化
struct seg{
double h,l,r; //平行于X轴扫描线的两个端点和纵坐标
int s; //从底向上扫描
seg(){}
seg(double a,double b,double c,int d):l(a),r(b),h(c),s(d){}
bool operator < (const seg&cmp)const{
return h<cmp.h;
}
}ss[maxn];
void pushup(int rt,int l,int r){ //节点 i 表示第i个点和第i+1个点之间的那个线段
if(cnt[rt])sum[rt]=X[r+1]-X[l]; //区间【l,r】那么就是指第l个线段到第r个线段的总长度
else if(l==r)sum[rt]=0;
else sum[rt]=sum[left]+sum[right];
}
void update(int L,int R,int c,int l,int r,int rt){
if(L<=l&&r<=R){
cnt[rt]+=c;
pushup(rt,l,r);
return ;
}
havemid;
if(L<=m)update(L,R,c,lson);
if(m<R)update(L,R,c,rson);
pushup(rt,l,r);
}
int Bin(double key,int n,double X[]){
int l=0,r=n-1;
while(l<=r){
havemid;
if(X[m]==key)return m;
if(X[m]<key)l=m+1;
else r=m-1;
}
return -1;
}
int main(){
int n,i,ca=1;
while(scanf("%d",&n)!=EOF){
if(n==0)break;
int m=0;
while(n--){
double a,b,c,d;
scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
X[m]=a;
ss[m++]=seg(a,c,b,1);
X[m]=c;
ss[m++]=seg(a,c,d,-1);
}
sort(X,X+m);
sort(ss,ss+m);
int k=1;
for(i=1;i<m;i++){
if(X[i]!=X[i-1])X[k++]=X[i];
}
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
double ret=0;
for(i=0;i<m-1;i++)
{
int l=Bin(ss[i].l,k,X);
int r=Bin(ss[i].r,k,X)-1;
if(l<=r)update(l,r,ss[i].s,0,k-1,1);
ret+=sum[1]*(ss[i+1].h-ss[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",ca++ , ret);
}
return 0;
}