http://acm.hdu.edu.cn/showproblem.php?pid=1542
看了几篇博客后总算理解了。。。
题意:给出n个矩形的左下角与右上角坐标,求矩形面积并
解题思路:
一开始是1~3,所以面积是2*h1(第2条线段高度-第1条线段高度),接着2~4,所以整个线段的oneMoreLen长度是3,面积是3*h2(第3条线段高度-第2条线段高度),
再到1~3,但这次是cover要加上-1,因为到顶,要减出来,面积是3*h3,结束。
其实就是对X坐标离散,建线段树,再一层一层计算面积。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define ll __int64
#define N 110
struct line
{
double left,right,h;
int flag;
}L[2*N];
map<double,int>M;
double X[2*N];
double XLi[2*N];
int cmp(line aa,line bb)
{
return aa.h<bb.h;
}
struct node
{
int left,right,cover;//cover表示该段成段覆盖的次数,但不向下更新
double oneMoreLen;//该区间覆盖一次以上的长度
}seg_tree[N*4];
void seg_built(int l,int r,int num)
{
seg_tree[num].left=l;
seg_tree[num].right=r;
seg_tree[num].cover=0;
seg_tree[num].oneMoreLen=0;
if(r!=l+1)
{
int mid=(l+r)>>1;
seg_built(l,mid,num<<1);
seg_built(mid,r,num<<1|1);
}
}
void push_up(int num)//向上更新
{
if(seg_tree[num].cover>0)
{
seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
return;
}
if(seg_tree[num].right==seg_tree[num].left+1)
{
seg_tree[num].oneMoreLen=0;
}
else
{
seg_tree[num].oneMoreLen=seg_tree[2*num].oneMoreLen+seg_tree[2*num+1].oneMoreLen;
}
}
void seg_update(int l,int r,int value,int num)
{
if(l>=seg_tree[num].right||r<=seg_tree[num].left) return;
if(l<=seg_tree[num].left&&r>=seg_tree[num].right)
{
seg_tree[num].cover+=value;
push_up(num);
return;
}
seg_update(l,r,value,2*num);
seg_update(l,r,value,2*num+1);
push_up(num);
}
int main()
{
int i,j,k;
int n,m,t;
t=1;
while(scanf("%d",&n)!=EOF && n )
{
M.clear();
m=0;
for(i=1;i<=n;i++)
{
double x1,x2,y1,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
X[++m]=x1;
L[m].left=x1;
L[m].right=x2;
L[m].h=y1;
L[m].flag=1;//线段记录
X[++m]=x2;
L[m].left=x1;
L[m].right=x2;
L[m].h=y2;
L[m].flag=-1;//线段记录
}
sort(X+1,X+1+m);
sort(L+1,L+1+m,cmp);
M[X[1]]=1;
XLi[1]=X[1];
j=1;
for(i=2;i<=m;i++)//X坐标离散化
{
if(X[i]!=X[i-1])
{
M[X[i]]=++j;
XLi[j]=X[i];
}
}
seg_built(1,j,1);
double sum=0;
for(i=1;i<m;i++)
{
seg_update(M[L[i].left],M[L[i].right],L[i].flag,1);
sum+=seg_tree[1].oneMoreLen*(L[i+1].h-L[i].h);
}
printf("Test case #%d\nTotal explored area: %.2lf\n\n",t++,sum);
}
}
/*
input:
2
10 10 20 20
15 15 25 25.5
0
output:
Test case #1
Total explored area: 180.00
*/