1. 程式人生 > >hdu 5532【最長非遞增子序列 時間復雜度 nlogn】

hdu 5532【最長非遞增子序列 時間復雜度 nlogn】

int urn 思路 while 最小值 復雜 include hdu nlogn

http://acm.split.hdu.edu.cn/showproblem.php?pid=5532

題意:由n個數組成的序列,如果去掉一個數後仍保持非遞增或者非遞減,則輸出YES,否則輸出NO.

思路:只需要求最長非遞增子序列的長度和最長非遞減子序列的長度,如果其中一個長度+1>=n,說明可以實現。(註意:用O(n*n)的算法會導致tle,此處用的是O(nlogn)的算法)

#include<stdio.h>
#define N 100010

int num[N],end1[N],end2[N];

int find1(int flag,int *end,int
low,int high) {//end1數組按非遞減順序存儲每一位的最小值 int mid; while(low < high) { mid = (low+high)>>1; if(end[mid] > flag) high = mid; else low = mid + 1; } return low; } int find2(int flag,int *end,int low,int high) {
//end2數組按非遞增順序存儲每一位的最大值 int mid; while(low < high) { mid = (low+high)>>1; if(end[mid] >= flag) low = mid+1; else high = mid; } return low; } int main() { int t,n,i,j,ans,len1,len2; scanf("%d",&t);
while(t--) { scanf("%d",&n); for(i = 1; i <= n; i ++) scanf("%d",&num[i]); end1[1] = end2[1] = num[1]; len1 = len2= 1; for(i = 2; i <= n; i ++) { if(num[i] >= end1[len1])//最長非遞減 ans = ++len1; else ans = find1(num[i],end1,1,len1+1); end1[ans] = num[i]; if(num[i] <= end2[len2])//最長非遞增 ans = ++len2; else ans = find2(num[i],end2,1,len2+1); end2[ans] = num[i]; } if(len1 + 1== n||len2 + 1== n||len1==n||len2==n) printf("YES\n"); else printf("NO\n"); } return 0; }

hdu 5532【最長非遞增子序列 時間復雜度 nlogn】