HDU - 5532(Almost Sorted Array)最長上升子序列
阿新 • • 發佈:2018-10-31
題意:
給出一個長度為n的數列,問刪除一個數後,剩下的數列能否成為一個非遞增或非遞減數列,可以輸出“YES”,否則輸出“NO”。
題解:
使用兩次最長上升子序列(LIS)。(抄了抄板子)
第一次,求非遞減序列的最大長度,不用做任何處理。
第二次,把原陣列取相反數(乘上一個-1),再進行一次LIS即可。
取兩次的最大值,如果大於等於n-1輸出“YES”。
附LIS(二分)程式碼:
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <string> #include <stack> #include <vector> #include <set> #include <map> #include <cmath> #include <sstream> #include <queue> #include <iomanip> #define FRER() freopen("in.txt","r",stdin); #define FREW() freopen("out.txt","w",stdout); #define clr(str,x) memset(str,x,sizeof(str)) #define INF 0x3f3f3f3f #define maxn 100010 typedef long long int ll; using namespace std; int a[maxn],b[maxn]; int Search(int num,int low,int high) { int mid; while(low<=high) { mid=(low+high)/2; if(num>=b[mid]) low=mid+1; else high=mid-1; } return low; } int LIS(int n) { memset(b,0,sizeof(b)); b[1]=a[1]; int len=1,pos; for(int i=2;i<=n;i++) { if(a[i]>=b[len]) { len++; b[len]=a[i]; } else { pos=Search(a[i],1,len); b[pos]=a[i]; // printf("pos=%d\n",pos); } } return len; } int main() { //FRER() //FREW() int T,n; scanf("%d",&T); while(T--) { memset(a,0,sizeof(a)); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } int ans1=LIS(n); for(int i=1;i<=n;i++) { a[i]=-a[i]; } int ans2=LIS(n); int ans=max(ans1,ans2); if(ans>=n-1) printf("YES\n"); else printf("NO\n"); } return 0; }