P1166【牛棚扩张】

一道离散化的题,不算难,但想不到用离散化思想也会暴力水掉。。。
描述 Description
  fj有n (1 <= N <= 25,000)个矩形牛棚,它们的墙均与坐标轴平行,而且其坐标在0..1,000,000之间,任意两个牛棚不能重叠,但可能会有公共的墙。
由于fj的奶牛持续增加,他不得不考虑扩张牛棚,一个牛棚可以扩张,当且仅当他的四周均不与其他牛棚接触,如果两个牛棚有一个公共角,那他们都是不可扩张的。
统计有多少牛棚可以扩张。
输入格式 Input Format
  * Line 1: 一个整数表示有 N个牛棚

* Lines 2..N+1:每行四个整数,表示一个牛棚的左下角的坐标和右上角的坐标。.


输出格式 Output Format
  * Line 1:一个整数表示有几个牛棚可以扩张.


下面说下本题的离散化要点:
 将每一个矩形拆成两条横边和两条竖边分开处理。对于每一条横边,我们只用记录它的x值,左右两端点的y值以及它所属的矩形编号i
(用在后面的记录),竖边同理; 
 然后是对横竖边分别进行的多关键字排序:(这里非常重要,因为每一个矩形都只会也只能与自己邻近的矩形有重合边的可能,所以对边的排序可以让“矩形”·有序化·,我们就可以只判断边i与边i+1是否满足条件即可。这就是离散化在这里可以降低时间复杂度到O(n)级别的原因)
 然后分别枚举横边与竖边,判断相邻两边是否满足条件并记录(这里注意迭代的细节问题)

差不多就是这样。






Code:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
struct LL
{
int x,y1,y2,Num;
}shu[52000];
struct LLL
{
int y,x1,x2,Num;
}heng[52000];
int N;
bool linee(LL a,LL b)
{return (a.x

bool listt(LLL a,LLL b)
{return (a.y

bool FFF[27000];

void init()
{
cin>>N;
int a,b,c,d;
for(int i=1;i<=N;i++)
{
scanf("%d %d %d %d",&a,&b,&c,&d);
//======存边
shu[i].x=a,shu[i].y1=b,shu[i].y2=d,shu[i].Num=i;
shu[i+N].x=c,shu[i+N].y1=b,shu[i+N].y2=d,shu[i+N].Num=i;

heng[i].y=b,heng[i].x1=a,heng[i].x2=c,heng[i].Num=i;
heng[i+N].y=d,heng[i+N].x1=a,heng[i+N].x2=c,heng[i+N].Num=i;
}
sort(shu+1,shu+2*N+1,linee);
sort(heng+1,heng+2*N+1,listt);
memset(FFF,1,sizeof(FFF));

/*cout<<"======================================="< for(int i=1;i<=2*N;i++)
printf("%d %d %d %d\n",shu[i].x,shu[i].y1,shu[i].y2,shu[i].Num);
cout<<"======================================="< for(int i=1;i<=2*N;i++)
printf("%d %d %d %d\n",heng[i].y,heng[i].x1,heng[i].x2,heng[i].Num);
*/
}
int main()
{
//freopen("expand8.in","r",stdin);
//freopen("a.out","w",stdout);
init();
int tail=shu[1].y2;
bool Q=0;
for(int i=1;i<2*N;i++)
{
Q=0;
if(shu[i].x==shu[i+1].x)
{
if(tail>=shu[i+1].y1)
{
Q=1;
FFF[shu[i].Num]=0,FFF[shu[i+1].Num]=0;
tail=max(tail,shu[i+1].y2);
}
}
if(!Q) tail=shu[i+1].y2;
}


tail=heng[1].x2;
for(int i=1;i<2*N;i++)
{
Q=0;
if(heng[i].y==heng[i+1].y)
{
if(tail>=heng[i+1].x1)
{
Q=1;
FFF[heng[i].Num]=0,FFF[heng[i+1].Num]=0;
tail=max(tail,heng[i+1].x2);
}
}
if(!Q) tail=heng[i+1].x2;
}

int Ans=0;
for(int i=1;i<=N;i++)
if(FFF[i])
Ans++;
cout< return 0;
}


你可能感兴趣的:(题解+注释)