雨へ痕
下一站路口,未知的道路

题意:
    给定n(1<= n <= 100000)个矩形,问最长的递增矩形序列。矩形A和B
A = ((xA1 , yA1 ), (xA2 ,yA2 )) 和 B = ((xB1 , yB1 ), (xB2 , yB2 )), 
如果xA2 < xB1 and yA2 < yB1 则 A <= B,问最长L1 <= L2  <= Ln的长度。

LIS序列必须保证单调性,由于我们到左下角的时候已经是定下了lis的位置,所以到右上角的时候必须用左下角确定的位置来更新,需要判断y谁更小。

#include <stdio.h>
#include
<stdlib.h>
#define inf 999999999
typedef
struct ppp{
int x,y;
int right;
int id;
}point;

inline
int max(int kk,int kkk)
{
return kk>kkk?kk:kkk;
}
inline
int min(int kk,int kkk)
{
return kk<kkk?kk:kkk;
}

point a[
200010]; //拆点
int pos[100002]; //每个矩形的最大链位置,这个位置是由左下角的点决定的
int cmp(const void *p,const void *q)
{
point
*pp,*qq;
pp
=(point *)p;
qq
=(point *)q;
if(pp->x != qq-> x) return pp->x - qq->x; //从左到右,保证后面的矩形只要满足y
return pp->right - qq->right; //保证同x的点先查询,查询只由小于x的点决定,更新的话会影响查询结果
}

int queue[100002]; //Lis
int top=-1;
int n;

int bf(int p,int q,int val)
{
int mid=(p+q)/2;
if(p>=q) return p;
if(queue[mid]>=val) return bf(p,mid,val);
return bf(mid+1,q,val);
}

int main()
{
int ans;
int i;
while(scanf("%d",&n)!=EOF)
{
ans
=1;top=-1;
queue[
0]=inf; //为了保证一开始左边的点都是链头
if(!n) break;
for(i=0;i<n;i++)
{
scanf(
"%d%d%d%d",&a[2*i].x,&a[2*i].y,&a[2*i+1].x,&a[2*i+1].y);
a[
2*i].right=0;
a[
2*i+1].right=1;
a[
2*i].id=a[2*i+1].id=i;
}
n
*=2;
qsort(a,n,
sizeof(a[0]),cmp);
for(i=0;i<n;i++)
{
if(a[i].right)
{
if(top<pos[a[i].id]) queue[++top]=a[i].y; //扩大LIS
else queue[pos[a[i].id]]=min(queue[pos[a[i].id]],a[i].y); //更新
}
else
{
if(queue[0]>=a[i].y) {pos[a[i].id]=0;continue;} //比链头的数还小也是链头
if(queue[top]<a[i].y) {pos[a[i].id]=top+1;continue;} //比链尾的数大为待插
pos[a[i].id]=bf(0,top,a[i].y); //中间值就二分求大于等于的第一个,从而更新
}
}
printf(
"%d\n",top+1);
}
return 0;
}
posted on 2011-04-15 18:19  雨^痕  阅读(215)  评论(0)    收藏  举报