第一次写二维线段树,听队友说各种纠结看不懂。刷完HH大牛的专辑中的一维了,怀着忐忑的心情看二维线段树,首先看最简单的,面积并。题意很简单啊,知道是二维线段树,想了想完全没思路。然后各种百度谷歌,找了几篇看着顺眼的blog看了思想,纠结了一小时左右,总算大概懂了。再看看HH的代码,简直是神来之笔,各种疑问蜂拥而至。跟队友讨论了n久,只剩PushUp和更新有点小纠结了。考虑到时间比较晚了,今天晚上就准备结束了。事后我又想了想,似乎有有点头绪了,果断又开电脑继续奋战,似乎是完全看懂了。然后自己敲了个代码纵向扫描,果断各种错误啊,接下来就是深入理解HH的代码了。在蛋疼了三小时之后,终于迎来了一道曙光,测试数据总算过了。不管结果如何,先submit,没想到,嘿嘿,居然Ac了,实在有点小兴奋啊。也算是了解了一点点二维线段树,虽说只是最基础的,不过我相信半个月之后也能达到入门级别啦。为自己加油!!!
ACcode:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using std::sort;
const int size=1111;
struct Seg
{
double ly,ry,hx;
int f;
Seg(){}
Seg(double a,double b,double c,int d):ly(a),ry(b),hx(c),f(d){}
bool operator < (const Seg &cmp)const {
return hx<cmp.hx;
}
}seg[size<<2];
struct Line
{
double len;
int v;
}tre[size<<2];
double Y[size<<1];
void build(int rt,int l,int r)
{
tre[rt].len=0;
tre[rt].v=0;
if (l==r) return ;
int m=(l+r)>>1;
build(rt<<1,l,m);
build(rt<<1|1,m+1,r);
}
void PushUp(int rt,int l,int r)
{
if (tre[rt].v)tre[rt].len=Y[r+1]-Y[l];
else if (l==r) tre[rt].len=0;
else tre[rt].len=tre[rt<<1].len+tre[rt<<1|1].len;
}
void update(int rt,int l,int r,int L,int R,int v)
{
if (L<=l&&r<=R)
{
tre[rt].v+=v;
PushUp(rt,l,r);
return ;
}
int m=(l+r)>>1;
if (L<=m) update(rt<<1,l,m,L,R,v);
if (R>m) update(rt<<1|1,m+1,r,L,R,v);
PushUp(rt,l,r);
}
int Bin(double key,int k,double Y[])
{
int l=0,r=k;
while (l<=r)
{
int m=(l+r)>>1;
if (Y[m]==key) return m;
else if (Y[m]<key) l=m+1;
else r=m-1;
}
return -1;
}
int main()
{
int n,m,i,k,L,R,cas=0;
double x1,x2,y1,y2,ans;
while (scanf("%d",&n)&&n)
{
m=0;
for (i=0;i<n;i++)
{
scanf("%lf %lf %lf %lf",&x1,&y1,&x2,&y2);
Y[m]=y1;Y[m+1]=y2;
seg[m++]=Seg(y1,y2,x1,1);
seg[m++]=Seg(y1,y2,x2,-1);
}
sort(Y,Y+m);
sort(seg,seg+m);
for (k=0,i=1;i<m;i++)
if (Y[i]!=Y[i-1]) Y[++k]=Y[i];
build(1,0,k-1);
for (ans=i=0;i<m-1;i++)
{
L=Bin(seg[i].ly,k,Y);
R=Bin(seg[i].ry,k,Y)-1;
if (L<=R) update(1,0,k-1,L,R,seg[i].f);
ans+=tre[1].len*(seg[i+1].hx-seg[i].hx);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",++cas,ans);
}
return 0;
}