#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define lowb(x) x&(-x)
#define N 105
#define LL long long
int n;
struct Line
{
double l,r,h;
int d;
Line(){}
Line(double a,double b,double c,int v)
{
l=a;r=b;
h=c;d=v;
}
}a[N<<2];
double all[N],sum[N<<2];
int cnt[N<<2];
bool cmp(Line a,Line b)
{
return a.h<b.h;
}
void push_up(int l,int r,int rt)
{
if(cnt[rt]){
sum[rt]=all[r+1]-all[l];
cout<<"sum"<<rt<<" = "<<sum[rt]<<endl;
}
else if(l==r){
sum[rt]=0;
cout<<"sum"<<rt<<"=0"<<endl;
}
else{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
cout<<"sum="<<rt<<"="<<(rt*2)<<"+"<<rt*2+1<<"="<<sum[rt]<<endl;
}
}
void update(int l,int r,int L,int R,int k,int rt)
{
cout<<"l,r, rt"<<l<<" "<<r<<" "<<rt<<endl;
if(l>=L && r<=R)
{
cout<<"query "<<l<<" "<<r<<endl;
cout<<"query rt="<<rt<<endl;
cnt[rt]+=k;
cout<<"cnt "<<rt<<"="<<cnt[rt]<<endl;
push_up(l,r,rt);
return ;
}
int m=(l+r)>>1;
if(L<=m)update(l,m,L,R,k,rt<<1);
if(R>m) update(m+1,r,L,R,k,rt<<1|1);
push_up(l,r,rt);
}
int main()
{
int kk=0;
while(cin>>n&&n)
{
double x1,y1,x2,y2;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
a[i]=Line(x1,x2,y1,1);//离散化过程
a[i+n]=Line(x1,x2,y2,-1);
all[i]=x1;all[i+n]=x2;
}
n<<=1;
sort(all+1,all+1+n);//离散化x坐标从下往上扫描
sort(a+1,a+1+n,cmp);//按高度排序
int m=unique(all+1,all+1+n)-all-1;//不同点的个数
double ans=0;
memset(cnt,0,sizeof(cnt));
memset(sum,0,sizeof(sum));
for(int i=1;i<n;i++)
{
int l=lower_bound(all+1,all+1+m,a[i].l)-all;//从下往上扫描找到该矩形的左右端点对应在x轴的下标
int r=lower_bound(all+1,all+1+m,a[i].r)-all;
cout<<l<<" "<<r-1<<" "<<a[i].d<<endl;
update(1,m-1,l,r-1,a[i].d,1);//更新该区间的值
cout<<"sum"<<sum[1]<<endl;
ans+=sum[1]*(a[i+1].h-a[i].h);
cout<<"ans="<<ans<<endl;
}
printf("Test case #%d\n",++kk);
printf("Total explored area: %.2f\n",ans);
printf("\n");
}
}
从调试过程可以看出:
第一次更新区间【1,2】d=1的时候sum【2】=10;
当 第三次查询【1,2】d=-1d的时候时候cnt[2]=0;
此时需要从它的子节点获取信息;
即此时执行sum2=sum4+sum5;
因为在此之前得到了sum5 =5
所以1-2区间得到更新。
同样的方法去处理3-4区间
划分区间的方法:
将每一段看成一个点:
例如离散化后的x坐标有4个
x1 x2 x3 x4
左闭右开
调试过程: