http://acm.hdu.edu.cn/showproblem.php?pid=1255
理解hdu1542后,这题也就改一下就行了。
题意:给出n个矩形的左下角与右上角坐标,求矩形覆盖两次以上的面积
解题思路:
与hdu1542思路一样,将X坐标离散建树再一层一层计算面积,唯一不同在于这里多一个量twoMoreLen,向上更新时维护好twoMoreLen就好
#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 N 1100
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,twoMoreLen;//该区间覆盖一次以上、两次以上的长度
}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;
seg_tree[num].twoMoreLen=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>=2)
{
seg_tree[num].twoMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
return;
}
if(seg_tree[num].cover==1)
{
if(seg_tree[num].right==seg_tree[num].left+1)//叶子节点
{
seg_tree[num].twoMoreLen=0;
seg_tree[num].oneMoreLen=XLi[seg_tree[num].right]-XLi[seg_tree[num].left];
}
else//非叶子节点,twoMoreLen要看下面的oneMoreLen长度
{
seg_tree[num].twoMoreLen=seg_tree[2*num].oneMoreLen+seg_tree[2*num+1].oneMoreLen;
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;
seg_tree[num].twoMoreLen=0;
}
else
{
seg_tree[num].oneMoreLen=seg_tree[2*num].oneMoreLen+seg_tree[2*num+1].oneMoreLen;
seg_tree[num].twoMoreLen=seg_tree[2*num].twoMoreLen+seg_tree[2*num+1].twoMoreLen;
}
}
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;
scanf("%d",&t);
while(t--)
{
scanf("%d",&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].twoMoreLen*(L[i+1].h-L[i].h);
}
printf("%.2lf\n",sum);
}
}
/*
input:
2
5
1 1 4 2
1 3 3 7
2 1.5 5 4.5
3.5 1.25 7.5 4
6 3 10 7
3
0 0 1 1
1 0 2 1
2 0 3 1
output:
7.63
0.00
*/