【LIS最長上升子序列】HDU5532 Almost Sorted Array
阿新 • • 發佈:2019-02-06
【題意】問刪除一個數能否讓陣列成為有序的。
【思路】求正反兩個 最長不下降子序列 長度就能保證,直接暴力超時,LIS nlogn。
【LIS】最長上升子序列:
我們有這樣一種思路,如果同樣長度的LIS,如果該LIS序列的最後一位越小,他的“潛力”就越大,也就是說,對於dp[i]來說,如果在前i個數中有幾種LIS解法,但是某一種的末尾的元素最小,我們就認為該元素的序列是較優的LIS,顯然想到單調的資料結構來處理 。
也就是說,LIS陣列儲存了到達當前長度時,最後一位的最小數字是多少。
【LIS程式碼】
#include<cstdio> #include<iostream> #include<cstring> #define MAXN 10000+10 int lis[MAXN],a[MAXN],n; using namespace std; int len; int find(int i){ int l,r,m; l=0,r=len; while(l<r){ m=l+r>>1; if(lis[m]>=a[i]) r=m; else l=m+1; } return l; } int main(){ scanf("%d",&n); for(register int i=1;i<=n;i++) scanf("%d",&a[i]); lis[1]=a[1];len++; for(register int i=2;i<=n;i++){ if(a[i]>lis[len]) lis[++len]=a[i]; else{ int pos=lower_bound(lis+1,lis+len,a[i])-lis; lis[pos]=a[i]; } } printf("%d",len); return 0; } --------------------- 本文來自 NOIAu 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net/NOIAu/article/details/72870205?utm_source=copy
【程式碼】本題的話,題意允許重複數字出現,也就是,最長不下降子序列 。將判斷改成,lower_bound改成upper_bound就可以了。
#include<bits/stdc++.h> #define fuck(x) std::cout<<"["<<#x<<"]:"<<x<<endl; using namespace std; const int M=1e5+5; int a[M]; int b[M]; int d[M]; int main()a { int n; int _; scanf("%d",&_); while(_--) { scanf("%d",&n); for(int i=1,j=n; i<=n; i++,j--) { scanf("%d",&a[i]); b[j]=a[i];//正反找兩遍LIS } d[1]=a[1];//把第一個放進來 int len=1;//長度當然是1 for(int i=2; i<=n; i++) { if(a[i]>=d[len])//如果新來的比前面的要大,放到後面,長度++。 d[++len]=a[i]; else//不然將插入位置替換成這個數 { int j=upper_bound(d+1,d+len+1,a[i])-d; d[j]=a[i]; } } int len2=1; d[1]=b[1]; for(int i=2; i<=n; i++) { if(b[i]>=d[len2]) d[++len2]=b[i]; else { int j=upper_bound(d+1,d+len2+1,b[i])-d; d[j]=b[i]; } } if(max(len,len2)>=n-1) printf("YES\n"); else printf("NO\n"); } return 0; }