poj1609 Tiling Up Blocks(LIS)

来源:互联网 发布:js遍历set集合对象 编辑:程序博客网 时间:2024/06/07 07:16

题意:堆积木,就像乐高玩具那种的,下面有凹陷处,上面有突出处,这样两块积木就可以拼接了。每个积木上下的左边和中间都有拼接处,规则是下面的积木的插孔必须大于或者等于上面的插孔时,才可以堆放;问最多可以堆放多高;

简单的最长不下降子序列,注意上下可以相等,和之前做过的最长上升子序列略有不同,数据10000,n^2会超时(这道题数据很弱,如果用n^2的方法来写也能过),所以用nlogn的方法来写,利用到了二分搜索,用STL里的lower_bound()和upper_bound()解决就很方便了;

iterator lower_bound(  ): 返回一个迭代器,指向键值>= key的第一个元素。

iterator upper_bound(  ):返回一个迭代器,指向键值> key的第一个元素。


#include<iostream>#include<cstdlib>#include<cstdio>#include<algorithm>#include<cstring>#include<map>#define INF 0x3f3f3f3f#define N 10010using namespace std;typedef struct block{    int x,y;}block;block p[N];int cmp(block a,block b)//排序,先x后y,这样排出的序列中p[i].x一定是按照升序来的;{    if(a.x==b.x)        return a.y<b.y;    else        return a.x<b.x;}int main(){    int i,n,ans,dp[N];    while(1)    {        scanf("%d",&n);        if(n==0)        {            printf("*\n");            break;        }        memset(p,0,sizeof(p));        fill(dp,dp+n,INF);        for(i=0;i<n;i++)            scanf("%d%d",&p[i].x,&p[i].y);        sort(p,p+n,cmp);        for(i=0;i<n;i++)            *upper_bound(dp,dp+n,p[i].y)=p[i].y;//由于排序后x是升序的,所以计算y最长不下降序列是多少就行了,又因为可以相等,所以用upper_bound();        ans=lower_bound(dp,dp+n,INF)-dp;        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击