本文共 1516 字,大约阅读时间需要 5 分钟。
时间复杂度:
O(nlogn)
//单调栈问题//分别计算从左向右和从右向左的最长上升子序列,分别存储到两个数组中import java.util.*; class Main{ static int n = 0, N = 1010; static int[] nums = new int[N]; static int[] left = new int[N], right = new int[N]; static int bs(int[] max, int len, int num){//找到从左到右第一个大于num的数字 int l = 0, r = len; while(l < r){ int mid = l + r >> 1;//+1防止mid不变造成死循环。 if(max[mid] < num)l = mid + 1; else r = mid; } return l; } public static void main(String[] args)throws Exception{ Scanner sc = new Scanner(System.in); int m = sc.nextInt(); for(int i = 1; i <= m; ++i)nums[i] = sc.nextInt(); int[] st = new int[N];//单调栈 int tt = -1; for(int i = 1; i <= m; ++i){ if(tt == -1)st[++tt] = nums[i]; if(tt >= 0 && st[tt] > nums[i]){ int index = bs(st, tt, nums[i]); st[index] = nums[i]; } if(st[tt] < nums[i])st[++tt] = nums[i]; left[i] = tt + 1; } tt = -1; for(int i = m; i >= 1; --i){ if(tt == -1)st[++tt] = nums[i]; if(tt >= 0 && st[tt] > nums[i]){ int index = bs(st, tt, nums[i]); st[index] = nums[i]; } if(st[tt] < nums[i])st[++tt] = nums[i]; right[i] = tt + 1; } int max = 0; for(int i = 1; i <= m; ++i){ max = Math.max(max, left[i] + right[i] - 1); } System.out.print(max); }}
转载地址:http://dfre.baihongyu.com/