[Swust OJ 585]--倒金字塔(LIS最长不下降子序列)

时间:2023-12-26 21:06:25

题目链接:http://acm.swust.edu.cn/problem/585/

Time limit(ms): 3000      Memory limit(kb): 65535
SWUST国的一支科学考察队到达了举世闻名的古埃及金字塔。 
关于金字塔的建造一直是一个未解之谜, 有着“西方史学之父”之称的希罗多德认为,金字塔的建造是人力和牲畜,花费20 年时间从西奈半岛挖掘天然的石头运送到埃及堆砌而成。也有不少人认为是外星人修建的。人们发现胡夫金字塔的经线把地球分成东、西两个半球,它们的陆地面积是相等的,这种“巧合”大概是外星人选择金字塔建造地点的用意。法国化学家戴维·杜维斯则认为,建造金字塔的巨石不是天然的,而是人工浇筑的。 
SWUST 国科考队的队员们正准备研究戴维·杜维斯提出的假说。为了研究这种假说,他们需要用到“倒金字塔模型”。所谓倒金字塔模型,即金字塔由N 层人工浇筑的巨石堆砌而成,非底层的任意一层巨石的长度和宽度都必须要小于等于它下面的一层巨石的长度和宽度。 
现在,科考队队员们打算用手里仅有N 块木板去模拟这个倒金字塔模型。请计算出科考队队员们能够构建的倒金字塔模型的最大高度。
Description
测试数据的第1 行,为一个正整数N(N <= 100000),表示科考队队员们手里一共有N 块木板。 
接下来N 行,每行两个数:a,b( a, b <= 100000),分别表示一块木板的长度与宽度。
Input
只有一个正整数,为最多可以堆叠的倒金字塔的高度。所有的木板厚度均为1。
Output
1
2
3
4
5
3
3 2
1 1
2 2
Sample Input
1
2
3
Sample Output
解题思路:先按照一个坐标为基准升序排序,然后求最长不下降子序列(LIS),
                 这里由于测试数据较多(100000),在dp时采用二分查找,这样T(n)=O(nlog2n).~~
关于LIS可以戳戳这里:http://www.cnblogs.com/zyxStar/p/4296704.html
代码如下:
 #include <iostream>
#include <algorithm>
using namespace std; struct node{
int x, y;
bool operator<(const node &tmp)const{
if (x != tmp.x)
return x < tmp.x;
return y < tmp.y;
}
}tower[]; int n, len, dp[]; int binary_search(int key, int low, int high){
while (low < high){
int mid = (low + high) >> ;
if (key >= dp[mid])
low = mid + ;
else high = mid;
}
return low;
} int main(){
int i, j;
while (cin >> n){
for (i = ; i < n; i++) cin >> tower[i].x >> tower[i].y;
sort(tower, tower + n);
dp[] = tower[].y, len = ;
for (i = ; i < n; i++){
if (dp[len] <= tower[i].y) j = ++len;
else
j = binary_search(tower[i].y, , len + );
dp[j] = tower[i].y;
}
cout << len << endl;
}
return ;
}