天天看点

codevs 1689 建造高塔

1689 建造高塔

 时间限制: 1 s

 空间限制: 128000 KB

 题目等级 : 钻石 Diamond

题目描述 Description

n有n种石块,石块能无限供应。每种石块都是长方体,其中第i种石块的长、宽、高分别为li、wi、hi。石块可以旋转,使得其中两维成为长度和宽度,第三维成为高度。如果要把一个石块放在另一个石块上面,必须保证上面石块的长和宽都分别严格小于下面石块的长和宽。这意味着,即使两块长宽相同的石块也不能堆砌起来。

现在神犇想知道,最多能用上多少块石头呢?

输入描述 Input Description

第一行,N; 

以下N行,每行三个数,表示第i种石头的长宽高。

输出描述 Output Description

一个整数,表示最多能用上多少块石头。

样例输入 Sample Input

3      
1 1 1      
2 2 2      
3 3 4      

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

N≤50000,其余数字≤maxlongint。

/*
排序+LIS
O(n*n)做法可以的60分
刚开始打的n*n的最长上升子序列
*/
/*
排序时一点小技巧
把结构体按长从小到大排序
如果长相等则把宽大的排前面
这样就可以转化成求宽的最长上升子序列了
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50010
using namespace std;
struct node
{
    int l;
    int s;
}e[maxn*6];
int n,tot,len,c[maxn*6];
int cmp(node x,node y)
{
    if(x.l<y.l)return 1;
    if(x.l==y.l&&x.s>=y.s)return 1;
    return 0;
}
int main()
{
    int i,j,k;
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        e[++tot].l=x;e[tot].s=y;
        e[++tot].l=x;e[tot].s=z;
        e[++tot].l=y;e[tot].s=z;
        e[++tot].l=y;e[tot].s=x;
        e[++tot].l=z;e[tot].s=x;
        e[++tot].l=z;e[tot].s=y;
    }
    sort(e+1,e+tot+1,cmp);
    for(i=1;i<=tot;i++)
    {
        if(e[i].s>c[len])
        c[++len]=e[i].s;
        else
        {
            //int mx=lower_bound(c+1,c+len+1,e[i].s)-c;
            int l=1,r=len,mx;
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(e[i].s<=c[mid])
                {
                    mx=mid;
                    r=mid-1;
                }
                else
                l=mid+1;
            }
            c[mx]=e[i].s;
        }
    }
    printf("%d
",len);
    return 0;
}