小红有两个长度为n的排列A和B。每个排列由[1,n]数组成,且里面的数字都是不同的。
现在要找到一个新的序列C,要求这个新序列中任意两个位置(i,j)满足:
如果在A数组中C[i]这个数在C[j]的后面,那么在B数组中需要C[i]这个数在C[j]的前面。
请问C序列的长度最长为多少呢?
小红有两个长度为n的排列A和B。每个排列由[1,n]数组成,且里面的数字都是不同的。
现在要找到一个新的序列C,要求这个新序列中任意两个位置(i,j)满足:
如果在A数组中C[i]这个数在C[j]的后面,那么在B数组中需要C[i]这个数在C[j]的前面。
请问C序列的长度最长为多少呢?
第一行一个整数,表示N。
第二行N个整数,表示A序列。
第三行N个整数,表示B序列。
满足:N<=50000
输出最大的长度
5 1 2 4 3 5 5 2 3 4 1
4
最长的C为1,3,4,5
n = int(input()) a = list(map(int, input().split())) b = list(map(int, input().split())) tmp = [] for i in range(n): tmp.append(a.index(b[i])) dp = [1] * (n) for i in range(1,n): for j in range(i): if tmp[i]<tmp[j]: dp[i] = max(dp[j]+1, dp[i]) print(max(dp))
import java.util.*; public class Main{ public static void main(String []args){ Scanner sc = new Scanner(System.in); int n = sc.nextInt(); HashMap<Integer,Integer> hs = new HashMap<>(); int[] index = new int[n]; for(int i = 0;i < n;i++){ hs.put(sc.nextInt(),i); } // 通过序列值映射下标 for(int i = 0;i < n;i++){ index[i] = (int)hs.get(sc.nextInt()); } System.out.println(getSequence(index, n)); } // 查找存储下标的数组最长降序子序列长度 public static int getSequence(int[] arr, int num){ // 考虑边界情况 if(num == 2) return arr[0] > arr[1]?2:1; else if(num == 1) return 1; // 新建一个数组存储降序子序列 int r = 0;// 记录des数组的下标位置 int[] des = new int[num]; des[r] = arr[r]; for(int i = 1;i < num;i++){ if(arr[i] < des[r]){ des[++r] = arr[i]; }else{ // r到达某一位置时,不是降序的 branching(des, r, arr[i]); } } return r + 1; } // 对子序列进行分支 public static void branching(int[] des, int r, int curr){ // 边界条件 if(des[0] < curr){ des[0]= curr; return; } if(r == 1){ des[0] = des[0] > curr ? des[0] : curr; //return;// 不需要return } // 分支策略 int l = 0; int m = 0; while(r - 1 > l){ m = (r + l) / 2; if(des[m] > curr) l = m; else r = m; } des[r] = curr; } }
import sys import bisect n = int(sys.stdin.readline().strip()) dic = {} for index, num in enumerate(list(map(int, sys.stdin.readline().split()))): dic[num] = index my_list = list(map(int, sys.stdin.readline().split())) for i in range(n): my_list[i] = dic[my_list[i]] if __name__ == '__main__': tmp = [my_list[0]] res = 1 for i in range(1, n): if my_list[i] < tmp[0]: tmp.insert(0, my_list[i]) res += 1 else: tmp[bisect.bisect(tmp, my_list[i])-1] = my_list[i] print(res)
import java.util.*; public class Main { public static void main(String []args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); if(n<=0) { System.out.println( 0 ); return; } int[] an = new int[n]; int[] bn = new int[n]; for( int i = 0 ; i < n ; i++ ) { an[i] = sc.nextInt(); } for( int i = n-1 ; i >-1 ; i-- ) { bn[i] = sc.nextInt(); } System.out.println(md( an , bn ,n)); } public static int md( int[] an , int[] bn , int n ) { if(n==1)return an[0]==bn[0]?1:0; int[] res = new int[n]; for( int i = 0 ; i < n ; i++ ) for(int j = 0 ; j<n ; j++) { if( i == 0 ) { if( j==0 ) { res[0] = an[0]==bn[0]?1:0; }else{ res[j] = an[i]==bn[j]?1:res[j-1]; } }else if(j == 0 ) { res[j] = res[j]==1?1:( an[i]==bn[j]?1:0 ); }else{ if( an[i] == bn[j] ) { res[j] = res[j-1]+1; }else{ res[j] = Math.max( res[j] ,res[j-1] ); } } } return res[n-1]; } }//思路2
import java.util.*; public class Main { public static void main(String []args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int[] b = new int[n]; HashMap<Integer , Integer> hs = new HashMap<>(); for(int i = 0 ; i < n ; i++) { hs.put( sc.nextInt() , i ); } for(int i = 0 ; i < n ; i++) { b[i] = (Integer) hs.get( sc.nextInt() ); } System.out.println( md( b , n ) ); } public static int md( int[] an , int n) { if(n<2)return 1; if(n==2)return an[0]>an[1]?2:1; int r = 0 ; int[] end = new int[n]; end[r] = an[r]; for( int i =1 ; i < n ; i++) { if( an[i] < end[r] ) { r++; end[r] = an[i]; }else{ cmp( end , r , an[i] ); } } return r+1; } public static void cmp( int[] cmp , int r , int target ) { if( cmp[0]<target ) { cmp[0] = target; return; } if( r==1 ) { cmp[0] = ( cmp[0]>target?cmp[0]:target ); } int l = 0 ; int m ; while( r-1 > l ) { m = (l+r)/2; if( cmp[m] > target ) { l = m ; }else{ r = m; } } cmp[r] = target; } }
#include <iostream> #include <algorithm> #include <cstring> #include <map> using namespace std; map<int ,int> mp; struct node{ int num; int rank; }arr[50007]; int in[50007]; int main() { int n, num; scanf("%d", &n); for (int i = 0; i < n; ++i) scanf("%d", &arr[i].num); for (int i = 0; i < n; ++i) { scanf("%d", &num); mp[num] = i + 1; } for (int i = 0; i < n; ++i) arr[i].rank = - mp[arr[i].num]; in[0] = arr[0].rank; int len = 1; for (int i = 1; i < n; ++i) { int adr = lower_bound(in, in + len, arr[i].rank) - in; if (len == adr) in[len ++] = arr[i].rank; else in[adr] = arr[i].rank; } printf("%d\n", len); return 0; }
思路:你仔细看看、想想就会知道其实这是一个最长下降子序列。我已开始就是想着吧最左边的1挪到最右边,那么肯定是满足条件的了,但是这样依赖,挪到右边之后的位置的右边假设还有数,那么这些数就废了,那么问题就是怎么挪哪些数到右边的时候尽量保证废了的数字尽量的少,那么你就按照下面的顺序给上面的数赋值顺序,你就会发现变成了最长下降子序列...
you see you see one day day的
import java.util.*; class Main { // public static int first(int[] a,int[] b){ // int[][] dp =new int[a.length+1][a.length+1]; // for(int i=1;i<=a.length;i++){ // for(int j=1;j<=a.length;j++){ // if(a[i-1]==b[j-1]) // dp[i][j] =dp[i-1][j-1]+1; // else // dp[i][j] =Math.max(dp[i-1][j],dp[i][j-1]); // } // } // return dp[a.length][a.length]; // } public static void main(String[] args) { Scanner in = new Scanner(System.in); int num = in.nextInt(); int[] arr1 = new int[num]; int[] arr2 = new int[num]; int[] map = new int[num + 1]; int[] need = new int[num]; for (int i = 0; i < num; i++) { arr1[i] = in.nextInt(); map[arr1[i]] = i; } for (int i = 0; i < num; i++) { arr2[i] = in.nextInt(); need[i] = map[arr2[i]]; } // System.out.println(Arrays.toString(need)); List<Integer> dp = new ArrayList<>(); dp.add(need[0]); for (int i = 1; i < num; i++) { if (need[i] < dp.get(dp.size() - 1))dp.add(need[i]); else { int bound = Collections. binarySearch(dp, need[i], (a, b)->b - a); //System.out.println(-bound-1); int index = -bound - 1; dp.set(index,need[i]); } } System.out.println(dp.size()); } }
import java.util.*; public class Main{ public static void main(String[] args){ Scanner scn=new Scanner(System.in); while(scn.hasNextInt()){ int n=scn.nextInt(); int[] a=new int[n]; int[] b=new int[n]; for(int i=0;i<n;i++) a[i]=scn.nextInt(); for(int i=0;i<n;i++) b[n-1-i]=scn.nextInt(); int[][] dp=new int[2][n+1]; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ dp[1][j]=a[i-1]==b[j-1]?dp[0][j-1]+1:Math.max(dp[0][j],dp[1][j-1]); } int[] temp=dp[0]; dp[0]=dp[1]; dp[1]=temp; } System.out.println(dp[0][n]); break; } } }
#include<bits/stdc++.h> using namespace std; int main() { int n; cin>>n; map<int,int>m; vector<int>b(n); for(int i=0;i<n;i++) { int x; cin>>x; m[x]=i; } for(int i=0;i<n;i++) { int y; cin>>y; b[i]=m[y]; } vector<int>dp; dp.push_back(b[0]); for(int i=1;i<n;i++) { if(b[i]<dp.back())dp.push_back(b[i]); else{ int pos=lower_bound(dp.begin(),dp.end(),b[i],greater<int>())-dp.begin(); dp[pos]=b[i]; } } cout<<dp.size()<<endl; return 0; }
import java.util.*; public class Main { // 动态规划,最长公共子序列 public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc = new Scanner(System.in); int N = sc.nextInt(); int[] A = new int[N+1]; int[] B = new int[N+1]; int[][] dp = new int[N+1][N+1]; // 读取数据 for(int i=N;i>0;i--) { A[i]= sc.nextInt(); } for(int i=1;i<=N;i++) { B[i]= sc.nextInt(); } // 格式化二维数组 for(int i=0;i<=N;i++) { for(int j=0;j<=N;j++) { dp[i][j]=0; } } // 判断最长的公共子序列 for(int i=1;i<=N;i++) { for(int j=1;j<=N;j++) { if(A[i]==B[j]) { dp[i][j]= Math.max(dp[i-1][j], dp[i][j-1])+1; }else { dp[i][j]= Math.max(dp[i-1][j], dp[i][j-1]); } } } //// 输出dp看看---调试用 // for(int i=0;i<=N;i++) { // for(int j=0;j<=N;j++) { // System.out.print(dp[i][j]+" "); // } // System.out.println(); // } System.out.println(dp[N][N]); } }
N = int(input()) list1 = list(map(int,input().split())) list2 = list(map(int,input().split())) list3 = [list1.index(i) for i in list2] #list3.reverse() dp = [0 for i in range(N)] size = 0 for x in list3: i,j = 0,size while i != j: m = (i+j)//2 if dp[m] > x: i = m + 1 else: j = m dp[i] = x size = max(size,i+1) print(size)