usac前面有一题是递归求矩形覆盖面积的,学到不少东西
离散化 把所有矩形离散化(就是将整个平面分成许多“竖条”或“横条”,对其操作),每个矩形都由四条边组成,分为纵边和横边。对纵边和横边分别扫描一次,以横边为例:
- 每个矩形的两条横边中,称下面的为始边,上面的为终边。
- 把每条横边以纵坐标从小到大排序,如果纵坐标相同,则应把始边排到终边之前。
- 依次枚举每条横边
- 如果当前边为始边,则把这条边的横向的所有点j的层数增加1,即为level[j]++。如果层数由0变为了1,则这一点一定是边缘点,总周长ans++。
- 如果当前边为终边,则把这条边的横向的所有点j的层数减少1,即为level[j]--。如果层数由1变为了0,则这一点一定是边缘点,总周长ans++。
同理按此方法扫描纵边,即可得到最后结果。
/*
ID:jinbo wu
TASK:picture
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int s,e,y;
bool ok;
}a[2][20500];
const int m=10000;
int ans=0;
int level[20500];
int n;
bool cmp(node a,node b)
{
return a.y<b.y||(a.y==b.y&&a.ok);
}
void solve(int k)
{
memset(level,0,sizeof(level));
sort(a[k]+1,a[k]+n+1,cmp);
for(int i=1;i<=n;i++)
{
if(a[k][i].ok)
{
for(int j=a[k][i].s;j<a[k][i].e;j++)
{
level[j]++;
if(level[j]==1)
ans++;
}
}
else
{
for(int j=a[k][i].s;j<a[k][i].e;j++)
{
level[j]--;
if(level[j]==0)
ans++;
}
}
}
}
int main()
{
freopen("picture.in","r",stdin);
freopen("picture.out","w",stdout);
int x1,x2,y1,y2;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x1>>y1>>x2>>y2;
x1+=m,x2+=m,y1+=m,y2+=m;
a[0][i*2-1].s=x1,a[0][i*2-1].e=x2,a[0][i*2-1].y=y1,a[0][i*2-1].ok=true;
a[0][i*2].s=x1,a[0][i*2].e=x2,a[0][i*2].y=y2,a[0][i*2].ok=false;
a[1][i*2-1].s=y1,a[1][i*2-1].e=y2,a[1][i*2-1].y=x1,a[1][i*2-1].ok=true;
a[1][i*2].s=y1,a[1][i*2].e=y2,a[1][i*2].y=x2,a[1][i*2].ok=false;
}
n=n*2;
solve(0);
solve(1);
cout<<ans<<endl;
}