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