第一行一个正整数N。 接下来N行。每行两个整数分别表示X 和 H X1 H1 X2 H2 … XN HN输入限制: 对于70%的数据:0<N<10^40<Xi<10^60<Hi<10^6100%的数据:0<N<10^60<Xi<10^60<Hi<10^6
一个整数,表示最多可以卖出的宝物数
4 3 2 1 1 1 3 1 2
3
按照一个维度排序后按照另一个维度寻找最长增加子序列即可,这个是>=的比较简单一点,注意不能用O(n2),要二分查找优化
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[][] ans = new int[n][2];
for(int i=0;i<n;i++){
ans[i][0] = scanner.nextInt();
ans[i][1] = scanner.nextInt();
}
Arrays.sort(ans,(a,b)->a[0]!=b[0]?a[0]-b[0]:a[1]-b[1]);
int[] arr = new int[n];
for(int i=0;i<n;i++)arr[i] = ans[i][1];
System.out.println(LIS(arr));
}
public static int LIS(int[] arr){
int[] dp = new int[arr.length];
int res = 0;
for(int num:arr){
int l = 0,r = res;
while (l<r){
int m = (l+r)/2;
if(dp[m]<num)l = m+1;
else r = m;
}
dp[l] = num;
if(l==res)res++;
}
return res;
}
} import sys class Z: def __init__(self,x,h): self.x = x self.h = h def __lt__(self,obj): if self.x != obj.x: return self.x < obj.x else: return self.h <obj.h N = int(input()) z_list =[] for i in range(N): x,h = map(int,sys.stdin.readline().strip().split()) z_list.append(Z(x,h)) z_list.sort() arr = [item.h for item in z_list] def binary_search(arr1,start,end,target): if start < end: mid =(start+end)//2 if arr1[mid]< target:#去找大于等于的位置 return binary_search(arr1,mid+1,end,target) else: return binary_search(arr1,start,mid,target) else: return start len_list=[arr[0]] for index in range(1,len(arr)): item = arr[index] pos = binary_search(arr1 =len_list,start=0,end=len(len_list),target= item) if len(len_list)==pos: len_list.append(item) else: len_list[pos]=item print(len(len_list))
import java.util.Arrays;
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n =sc.nextInt();
int[][] arr=new int[n][2];
for(int i=0;i<n;i++){
arr[i][0]=sc.nextInt();
arr[i][1]=sc.nextInt();
}
Arrays.sort(arr,(a,b)->a[0]==b[0] ? a[1]-b[1]:a[0]-b[0]);
//用lambda改写构造器,按照第一个元素大小升序,相等则按照第二个元素倒序
//a[1]-b[1]>0,则a[1],b[1]交换位置
int[] nArr=new int[n];
for(int i=0;i<n;i++) nArr[i]=arr[i][1];
System.out.println(nout(nArr));
}
public static int out(int[] nArr){//寻找最长增子序列动态规划
int result=0;
int len=nArr.length;
int[] dp=new int[len];
//dp[i]代表以nArr[i]结尾的上升子序列长度!!!
Arrays.fill(dp,1);
for(int i=1;i<len;i++){
for(int j=0;j<i;j++){
if(nArr[i]>nArr[j])
dp[i]=Math.max(dp[i],dp[j]+1);
}
}
for(int i=0;i<len;i++){
result=Math.max(result,dp[i]);
}
return result;
}
public static int nout(int[] nArr){//优化后
int len = nArr.length;
if (len <= 1) {
return len;
}
// tail 数组的定义:长度为 i + 1 的上升子序列的末尾最小是几
int[] tail = new int[len];
// 遍历第 1 个数,直接放在有序数组 tail 的开头
tail[0] = nArr[0];
// end 表示有序数组 tail 的最后一个已经赋值元素的索引
int end = 0;
for (int i = 1; i < len; i++) {
// 【逻辑 1】比 tail 数组实际有效的末尾的那个元素还大
if (nArr[i] > tail[end]) {
// 直接添加在那个元素的后面,所以 end 先加 1
end++;
tail[end] = nArr[i];
} else {
// 使用二分查找法,在有序数组 tail 中
// 找到第 1 个大于等于 nums[i] 的元素,尝试让那个元素更小
int left = 0;
int right = end;
while (left < right) {
// 选左中位数不是偶然,而是有原因的,原因请见 LeetCode 第 35 题题解
// int mid = left + (right - left) / 2;
int mid = left + ((right - left) >>> 1);
if (tail[mid] < nArr[i]) {
// 中位数肯定不是要找的数,把它写在分支的前面
left = mid + 1;
} else {
right = mid;
}
}
// 走到这里是因为 【逻辑 1】 的反面,因此一定能找到第 1 个大于等于 nums[i] 的元素
// 因此,无需再单独判断
tail[left] = nArr[i];
}
// 调试方法
// printArray(nums[i], tail);
}
// 此时 end 是有序数组 tail 最后一个元素的索引
// 题目要求返回的是长度,因此 +1 后返回
end++;
return end;
}
}
//out是动态规划,通过率只有80%
//nout优化后,通过了
借鉴了楼上大哥的
n=int(input()) a=[[int(i) for i in input().split()]for _ in range(n)] a=sorted(a) a=[i[1]for i in a] f = [0]*len(a) ans = 0 for i in a: l = 0 r = ans while l < r: m = (l + r) >> 1 if f[m] < i: l = m + 1 else: r = m f[l] = i if l == ans: ans += 1 print(ans)
var num = readline();
var arr= [];
var n = null;
while(n = readline()){
n=n.split(" ").map(item => {
return Number(item)
})
arr.push(n)
}
arr.sort((d1, d2) => {
return d1[0] != d2[0] ? d1[0] - d2[0] : d1[1] - d2[1]
});
function LIS(num, arr) {
var temp = [];
for (var i = 0; i < num; i++) {
temp.push(arr[i][1]);
}
let newArr = new Array(num);
newArr[0] = temp[0]
let end = 0;
for (var k = 0; k < num; k++) {
if (temp[k] > newArr[end]) {
end++;
newArr[end] = temp[k];
} else {
let left = 0 ;
let right = end ;
while(left < right){
let mid = left + ((right - left) >> 1);
if(newArr[mid] < temp[k]){
left = mid + 1;
} else {
right = mid;
}
}
newArr[left] = temp[k]
}
}
return end + 1
}
console.log(LIS(num, arr)) ; input: [[32],[11],[13],[12]] sorted(input):[[11],[12],[13],[32]]
def binary_search(nums,left,right,val):
mid = 0
while left < right:
mid = (left+right) // 2
if val > nums[mid]:
left = mid +1
else:
right = mid
return left
def LIS(N,prices):
res = []
for i in range(N):
if not res or prices[i] > res[-1]:
res.append(prices[i])
else:
idx = binary_search(res, 0, len(res), prices[i])
res[idx] = prices[i]
return len(res)
def main():
N = int(input())
prices = []
for i in range(N):
prices.append(list(map(int,input().split())))
prices.sort()
h = [a[1] for a in prices]
return LIS(N,h)
print(main())
n = int(input()) nums = [] for _ in range(n): nums.append(list(map(int, input().split()))) nums.sort(key = lambda x:[x[0], x[1]]) res = [] for i in range(n): if not res&nbs***bsp;nums[i][1] >= res[-1]: res.append(nums[i][1]) else: l, r = 0, len(res)-1 while l <= r: mid = (l+r)//2 if res[mid] < nums[i][1]: l = mid + 1 elif res[mid] >= nums[i][1]: r = mid - 1 res[l] = nums[i][1] print(len(res))
这种思路比较容易理解:但是只有60%通过率,时间复杂度太高了
import sys
def helper(res):
res.sort()
nums = []
for i in res:
nums.append(i[1])
#对nums进行一次最长上升子序列即可
dp = [1]*len(nums)
for i in range(len(nums)):
for j in range(i):
if nums[j]<nums[i]:
dp[i] = max(dp[i],dp[j]+1)
return max(dp)
pass
if __name__ == "__main__":
n = int(sys.stdin.readline().strip())
res = []
for i in range(n):
line = sys.stdin.readline().strip()
values = list(map(int, line.split(' ')))
res.append(values)
out = helper(res)
print(out)
class BIT:
def __init__(self,bound):
self.bound = bound
self.tree = {}
def updateAt(self,i,val):
while i <= self.bound:
if i not in self.tree:
self.tree[i] = val
if self.tree[i] > val:
break
self.tree[i] = max(self.tree[i],val)
i += i&-i
def maxUntil(self,i):
res = 0
while i>0:
if i in self.tree:
res = max(res,self.tree[i])
i -= i&-i
return res
if __name__=="__main__":
n = int(raw_input())
bound,items = n,[]
hs = []
for i in xrange(n):
x,h = map(int,raw_input().split())
items.append((x,h))
hs.append(h)
hs.sort()
hmap = {}
for i,h in enumerate(hs):
if h not in hmap:
hmap[h] = i+1
items.sort()
bit = BIT(bound)
res = 0
for x,h in items:
preMax = bit.maxUntil(hmap[h]-1)
bit.updateAt(hmap[h],preMax+1)
res = max(res,preMax+1)
print res
n = int(input()) goods = [] for i in range(n): goods.append(list(map(int,input().split()))) goods.sort(key = lambda x:(x[0],x[1])) stack = [] for i in range(len(goods)): # print(stack) if not stack or stack[-1]<=goods[i][1]: stack.append(goods[i][1]) continue for k in range(len(stack)): if stack[k] < goods[i][1]: continue else: stack[k] = goods[i][1] break print(len(stack))
def binaysearch(nums,left,right,val): while left < right: mid = (left + right) // 2 if nums[mid] >= val: right = mid elif nums[mid] < val: left = mid + 1 return left def ans(nums,num): nums = sorted(nums,key = lambda x:(x[0],x[1])) temp = [0]*num for i in range(num): temp[i] = nums[i][1] res = [] for i in range(num): if res == []&nbs***bsp;res[-1] < temp[i]: res.append(temp[i]) else: idx = binaysearch(res, 0, len(res), temp[i]) res[idx] = temp[i] return len(res) if __name__ == "__main__": num = int(input()) #宝物的数量 nums = [] for i in range(num): nums.append(list(map(int,input().split()))) print(ans(nums,num))
//参考大佬们的方法,注意这题的最长子序列需要>=而不是>
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[][] nums = new int[n][2];
for (int i = 0; i < n; i++) {
nums[i][0] = sc.nextInt();
nums[i][1] = sc.nextInt();
}
sc.close();
Arrays.sort(nums, (a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
int[] f = new int[n];
f[0] = nums[0][1];
int idx = 0;
for (int i = 1; i < n; i++) {
if (nums[i][1] >= f[idx]) {
f[++idx] = nums[i][1];
} else {
int lo = 0, hi = idx;
while (lo < hi) {
int m = (hi - lo) / 2 + lo;
if (f[m] < nums[i][1]) {
lo = m + 1;
} else {
hi = m;
}
}
f[lo] = nums[i][1];
}
}
System.out.println(idx + 1);
}
} public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[][] goods = new int[n][2];
for(int i = 0; i < n; i++) {
goods[i][0] = in.nextInt();
goods[i][1] = in.nextInt();
}
System.out.println(saleGoods(goods));
}
private static int saleGoods(int[][] goods) {
int len = goods.length;
Arrays.sort(goods, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] == o2[0] ? o1[1] - o2[1] : o1[0] - o2[0];
}
});
int[] nums = new int[len];
for(int i = 0; i < len; i++) {
nums[i] = goods[i][1];
}
return lengthOfLIS(nums);
}
private static int lengthOfLIS(int[] nums) {
int len = nums.length;
int[] dp = new int[len];
int maxLen = 0;
for(int num : nums) {
int left = 0, right = maxLen;
while(left < right) {
int mid = (left + right) >> 1;
if(num > dp[mid]) {
left = mid + 1;
} else {
right = mid;
}
}
dp[left] = num;
if(right == maxLen) {
maxLen++;
}
}
return maxLen;
}
} #include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int n;
cin>>n;
vector<vector<int>> goods(n,vector<int>(2,0));
for(int i=0;i<n;i++)
{
cin>>goods[i][0];
cin>>goods[i][1];
}
//对X升序排序
if(n<=0) return 0;
sort(goods.begin(),goods.end(),[](vector<int>& a,vector<int>& b){return a[0]!=b[0]?(b[0]-a[0]>0):(b[1]-a[1]>0);});
//寻找最长上升子序列
vector<int> d(n+1,0);
int len=0;
for(int i=1;i<n;i++)
{
int hig=len;
int low=0;
int mid=(low+hig)/2;
while(low<hig)
{
mid=(low+hig)/2;
if(d[mid]<goods[i][1])
low=mid+1;
else
hig=mid;
}
d[low]=goods[i][1];
if(len==low) len++;
}
cout<<len<<endl;
return 0;
} n = int(input()) WoW_goods = [] for i in range(n): goods = list(map(int, input().split())) WoW_goods.append(goods) # print(WoW_goods) WoW_goods.sort(key=lambda x: [x[0], x[1]]) # print(WoW_goods) H = [WoW[1] for WoW in WoW_goods] # print(H) LIS = [H[0]] import bisect for i in range(1, n): idx = bisect.bisect_left(LIS, H[i]) if idx==len(LIS): LIS.append(H[i]) else: LIS[idx] = H[i] print(len(LIS))
#include <bits/stdc++.h>
using namespace std;
struct node{
int x;
int h;
bool operator < (const node& ch)const{
if(x == ch.x) return h < ch.h;
return x < ch.x;
}
};
int main(){
int n;
cin>>n;
node N[n];
int s[n];
int cnt = -1;
for(int i = 0; i < n; i++) cin>>N[i].x>>N[i].h;
sort(N, N+n);
int l, r, mid;
for(int i = 0; i < n; i++){
if(cnt == -1 || s[cnt] <= N[i].h){
s[++cnt] = N[i].h;
continue;
}
l = 0;
r = cnt;
while(l <= r){
mid = l + (r - l) / 2;
if(s[mid] < N[i].h){
l = mid + 1;
}
else {
r = mid - 1;
}
}
s[l] = N[i].h;
}
cout<<cnt+1<<endl;
return 0;
} 这个为应该正确的代码(差别在二分中的第31行):#include <bits/stdc++.h>
using namespace std;
struct node{
int x;
int h;
bool operator < (const node& ch)const{
if(x == ch.x) return h < ch.h;
return x < ch.x;
}
};
int main(){
int n;
cin>>n;
node N[n];
int s[n];
int cnt = -1;
for(int i = 0; i < n; i++) cin>>N[i].x>>N[i].h;
sort(N, N+n);
int l, r, mid;
for(int i = 0; i < n; i++){
if(cnt == -1 || s[cnt] <= N[i].h){
s[++cnt] = N[i].h;
continue;
}
l = 0;
r = cnt;
while(l <= r){
mid = l + (r - l) / 2;
if(s[mid] <= N[i].h){
l = mid + 1;
}
else {
r = mid - 1;
}
}
s[l] = N[i].h;
}
cout<<cnt+1<<endl;
return 0;
}
n = int(input()) places = [ list(map(int,input().split())) for _ in range(n)] places.sort(key=lambda l:(l[0],l[1]),reverse=False) # print(places) dp = [1] for i in range(1,len(places)): max_dp = 0 for j in range(0,i): if places[i][1] > places[j][1] and dp[j]>max_dp: max_dp = dp[j] dp.append(max_dp+1) max_dp = 0 for i in dp: if i>max_dp: max_dp = i print(max_dp)