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