这个是线段树的经典题目了。
求n个矩形的面积并。
解法:把y坐标离散化,输入的矩形转换成两条平行于y轴的线(然后按x坐标排序)分别为入边和出边,然后对y轴建立线段树,依次插入线段。这个做法文字不好解释,具体的看代码吧。
#include
#include
#include
#include
using namespace std;
const int maxn=1101;
int ans;
struct
{
int l,r,x;
int y1,y2;
bool ture;
int count;
}tr[10000];
struct data
{
int x,y1,y2,count;
bool operator <(const
data &xx) const
{
return(x
}
}d[maxn*2];
int y[maxn*2];
int maketree(int t,int l,int r)
{
tr[t].l=l;
tr[t].r=r;
tr[t].y1=y[l];
tr[t].y2=y[r];
tr[t].ture=1;
tr[t].count=0;
if(l+1==r)
return(0);
int mid=(l+r)/2;
maketree(t*2,l,mid);
maketree(t*2+1,mid,r);
}
int pushdown(int t)
{
tr[t*2].x=tr[t].x;
tr[t*2].count=tr[t].count;
tr[t*2+1].x=tr[t].x;
tr[t*2+1].count=tr[t].count;
}
int insert(int t,int y1,int y2,data &d)
{
if(tr[t].y1==y1&&tr[t].y2==y2)
{
if(tr[t].ture)
{
if(tr[t].count>0)
{
int txt=y2-y1;
ans+=txt*(d.x-tr[t].x);
}
tr[t].count+=d.count;
tr[t].x=d.x;
return(0);
}
}
if(tr[t].ture)
pushdown(t);
tr[t].ture=0;
int
mid=(tr[t].l+tr[t].r)/2;
mid=y[mid];
if(mid<=y1)
insert(t*2+1,y1,y2,d);
else
if(y2<=mid)
insert(t*2,y1,y2,d);
else
{
insert(t*2,y1,mid,d);
insert(t*2+1,mid,y2,d);
}
}
int main()
{
int n;
while(1)
{
int x1,x2,y1,y2;
scanf("%d %d %d
%d",&x1,&y1,&x2,&y2);
if(x1==-1&&y1==-1&&x2==-1&&y2==-1)
break;
d[1].x=x1;
d[1].y1=y1;
d[1].y2=y2;
d[2].x=x2;
d[2].y1=y1;
d[2].y2=y2;
d[1].count=1;
d[2].count=-1;
y[1]=y1;
y[2]=y2;
for(int i=2;;i++)
{
scanf("%d
%d %d %d",&x1,&y1,&x2,&y2);
int
now=2*i-1,next=now+1;
d[now].x=x1;
d[now].y1=y1;
d[now].y2=y2;
d[next].x=x2;
d[next].y1=y1;
d[next].y2=y2;
d[now].count=1;
d[next].count=-1;
y[now]=y1;
y[next]=y2;
if(x1==-1&&y1==-1&&x2==-1&&y2==-1)
{
n=i-1;
break;
}
}
sort(y+1,y+2*n+1);
sort(d+1,d+2*n+1);
maketree(1,1,2*n);
ans=0;
for(int i=1;i<=2*n;i++)
{
insert(1,d[i].y1,d[i].y2,d[i]);
}
printf("%d\n",ans);
}
return 0;
}