天天看點

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;
}