12
/*
对长方形的宽w排序,本题化简为对长l求最长上升子序列。
本题只需求最长上升子序列的 长度,可优化到O(nlogn)
*/
#include
using namespace std;
#define N 1000000
struct rectangle {
int w = 0, l = 0;
} a[N];
int dp[N];
bool cmp(rectangle x, rectangle y){
return x.w == y.w ? x.l < y.l : x.w < y.w;
}
int main()
{
// freopen("input.txt", "r", stdin);
int n;
cin >> n;
for(int i = 0; i < n; i++) {
cin >> a[i].w >> a[i].l;
}
sort(a, a + n, cmp);
dp[0] = a[0].l;
int len = 1;
for(int i = 1; i < n; i++) {
if(a[i].l >= dp[len-1]) {
dp[len++] = a[i].l;
} else {
*(upper_bound(dp, dp + len, a[i].l)) = a[i].l;
}
}
cout << len << endl;
return 0;
}
编辑于 2019-07-05 12:12:17
回复(5)
6
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.TreeSet;
public class Solution3_搭积木 {
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(bf.readLine());
//保存积木的宽高的二维数组
int[][] bricks = new int[n][2];
String[] strs;
for (int i = 0; i < n; i++) {
strs = bf.readLine().split(" ");
bricks[i][0] = Integer.parseInt(strs[0]);
bricks[i][1] = Integer.parseInt(strs[1]);
}
if (n==1){
System.out.println(1);
return;
}
//按照宽进行排序,然后求长度的最长上升子序列
Arrays.sort(bricks, (a, b) -> a[0] - b[0]);
/**
* 我们按照宽度从小到大对 bricks 进行了排序
* dp数组中存储的数积木的长度,它是一个上升的数组,这样才能保证积木的层叠
*/
int[] dp = new int[n];
int count = 0;//层数
for (int i = 0; i < n; i++) {
if (count == 0 || bricks[i][1] >= dp[count - 1]) {
//当当前积木的长度 >= dp数组中保存的最大积木长度,那我们就将它加入到 dp 数组中,并且层数加一
dp[count] = bricks[i][1];
count++;
}else {
/**
* 这里解释一下:当我们加入的积木 bricks[i][1],它的长度小于dp中的最大长度
* 我们需要在数组dp中找到 <= bricks[i][1] 最接近的值的索引 index,将它替换成现在的长度 bricks[i][1]
* 为什么要替换: dp数组中积木的宽度都是小于 bricks[i]的,积木bricks[i]的宽度比dp[index]宽度大,
* 而且bricks[i]的长度 >= dp[index],在堆积木情况下,当然是优先选择宽度和长度更大的积木。
*/
int index = lowerBound(dp, 0, count, bricks[i][1]);
dp[index] = bricks[i][1];
}
}
System.out.println(count);
}
/**
* C++中存在的两个方法,用java实现一下
* ower_bound算法要求在已经按照非递减顺序排序的数组中找到第一个大于等于给定值key的那个数的索引,
* 其基本实现原理是二分查找
*/
public static int lowerBound(int[] nums,int l,int r,int target){
while(l
int m = (l+r)/2;
if(nums[m]>=target) r= m;
else l = m +1;
}
return l;
}
/**
* upper_bound函数要求在按照非递减顺序排好序的数组中找到第一个大于给定值key的那个数索引,
* 其基本实现原理是二分查找
*/
public static int upperBound(int []nums ,int l,int r, int target){
while(l
int m = (l+r)/2;
if(nums[m]<=target) l = m+1;
else r = m;
}
return l;
}
}
发表于 2019-08-03 15:44:14
回复(6)
2
/*
哪位大佬帮看一下啊?小数据测试都没问题,当积木数量到了10000之后,就报错了。找了很久不知道哪里出问题了 Q^Q public class DaJiMu {
public static void main(String[] args) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int num = Integer.parseInt(bufferedReader.readLine());
int[][] jimu = new int[num][2];
for (int i = 0; i < num; i++){
String[] temp = bufferedReader.readLine().split(" ");
jimu[i][0] = Integer.parseInt(temp[0]);
jimu[i][1] = Integer.parseInt(temp[1]);
}
Arrays.sort(jimu, new Comparator() { @Override public int compare(int[] o1, int[] o2) {
return o1[0] != o2[0]? o1[0] - o2[0] : o1[1] - o2[1];
}
});
if( num == 1){
System.out.print(1);
return;
}
int max = 0;
int[] len = new int[num];
len[0] = 1;
//求最长递归子序列
for (int i = 1; i < num; i++){
int lastADDIndex = binarySearch(jimu, jimu[i][1], 0, i - 1);
//若非递减,则选择max(len[i-1]+1, len[差值最小]+1)较大的长度。
if (jimu[i][1] >= jimu[i-1][1])
if(lastADDIndex != -1)
len[i] = Math.max(len[i-1] + 1, len[lastADDIndex] + 1);
else
len[i] = len[i-1] + 1;
else{
if(lastADDIndex != -1){
len[i] = len[lastADDIndex] + 1;
}else
len[i] = 1;
}
if( max < len[i])
max = len[i];
}
System.out.print(max);
}
public static int binarySearch(int[][] arr, int key, int start, int end){ int max = -1;
int min = 1000000000;
while(start <= end){
int mid = start + (end - start) / 2;
if(arr[mid][1] <= key) { </