题目:http://poj.org/problem?id=1177
分析:(括号匹配)首先把矩形的上边界作为“左括号”边,下边界作为“右括号”边,然后上下排序。假定排完序之后是下
面的状态:(())()(()()(()))
考虑“最外侧”的括号的数量。显然上面的那个串是(()) & () & (()()(()))
有六个最外侧括号,那么边界数量就是6。排序的复杂度O(nlogn),对于上面的思路,针对横边来说,如果并不是完全包括的
怎办,那就是将边分割成一些小段在用括号匹配。 括号匹配用到此题恰到好处即在于可以有效处理掉重复覆盖避免重复计算边
的问题。因为先将每个矩形的上、下边附一个标号1、-1。而对于此题有一个性质是,无论矩形怎么覆盖,最终对于某一小段边
一定会有一个对应的边存在。那么1、-1正好起到匹配的作用。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int maxn = 10005;
struct NODE
{
int cankao,weizhi,st,en; //weizhi为表明匹配边
}nodex[maxn],nodey[maxn];
int mapx[2*maxn],mapy[2*maxn],lenx[maxn],leny[maxn],vist[maxn];
bool cmp(NODE n1,NODE n2)
{
return n1.cankao<n2.cankao;
}
int main()
{
int n,i,j,x1,y1,x2,y2;
memset(mapx,0,sizeof(mapx));
memset(mapy,0,sizeof(mapy));
scanf("%d",&n);
for(i=0; i<n; i++) //存信息
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1+=maxn;
y1+=maxn;
x2+=maxn;
y2+=maxn;
mapx[x1]=mapx[x2]=mapy[y1]=mapy[y2]=1;
nodex[2*i].cankao=y1;
nodex[2*i].weizhi=1;
nodex[2*i].st=x1;
nodex[2*i].en=x2;
nodex[2*i+1].cankao=y2;
nodex[2*i+1].weizhi=-1;
nodex[2*i+1].st=x1;
nodex[2*i+1].en=x2;
nodey[2*i].cankao=x1;
nodey[2*i].weizhi=1;
nodey[2*i].st=y1;
nodey[2*i].en=y2;
nodey[2*i+1].cankao=x2;
nodey[2*i+1].weizhi=-1;
nodey[2*i+1].st=y1;
nodey[2*i+1].en=y2;
}
stable_sort(nodex,nodex+2*n,cmp);
stable_sort(nodey,nodey+2*n,cmp);
int tmpx=0,tmpy=0,ans=0;
for(i=0; i<2*maxn; i++)
{
if(mapx[i])
{
mapx[i]=tmpx;
lenx[tmpx++]=i;
}
if(mapy[i])
{
mapy[i]=tmpy;
leny[tmpy++]=i;
}
}
for(i=0; i<2*n; i++) //离散化
{
nodex[i].st=mapx[nodex[i].st];
nodex[i].en=mapx[nodex[i].en];
nodey[i].st=mapy[nodey[i].st];
nodey[i].en=mapy[nodey[i].en];
}
memset(vist,0,sizeof(vist));
for(i=0; i<2*n; i++)
{
for(j=nodex[i].st; j<nodex[i].en; j++)
{
vist[j]+=nodex[i].weizhi;
if(vist[j]==0) //匹配成功
ans+=lenx[j+1]-lenx[j];
}
}
memset(vist,0,sizeof(vist));
for(i=0; i<2*n; i++)
{
for(j=nodey[i].st; j<nodey[i].en; j++)
{
vist[j]+=nodey[i].weizhi;
if(vist[j]==0)
ans+=leny[j+1]-leny[j];
}
}
printf("%d\n",2*ans);
return 0;
}