第一行一个正整数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)