1. 程式人生 > >UVa 10534 波浪子序列(快速求LIS)

UVa 10534 波浪子序列(快速求LIS)

urn const scan .net nlog 遞增 problem ios 波浪

https://vjudge.net/problem/UVA-10534

題意:
給定一個長度為n的整數序列,求一個最長子序列(不一定連續),使得該序列的長度為2k+1,前k+1個數嚴格遞增,後k+1個數嚴格遞減。

思路:

先正著求一遍LIS,再反著求一遍LIS。

當然求法是得采用O(nlogn)的求法,這個網上有很多解釋,我就不多介紹了。

最後的話枚舉一遍就可以了,詳見代碼。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5
#include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long LL; 13 typedef pair<int,int> pll; 14 const int INF=0x3f3f3f3f; 15 const int maxn=10000+5; 16 17
int n; 18 int a[maxn],r_a[maxn],g[maxn],d1[maxn],d2[maxn]; 19 20 int main() 21 { 22 //freopen("D:\\input.txt","r",stdin); 23 while(~scanf("%d",&n)) 24 { 25 for(int i=0;i<n;i++) 26 { 27 scanf("%d",&a[i]); 28 r_a[n-i-1]=a[i]; 29 }
30 31 int ans1=0; 32 for(int i=1;i<=n;i++) g[i]=INF; 33 for(int i=0;i<n;i++) 34 { 35 int k=lower_bound(g+1,g+n+1,a[i])-g; 36 d1[i]=k; //記錄了前i個數的最長子序列 37 g[k]=a[i]; 38 ans1=max(ans1,d1[i]); 39 } 40 41 int ans2=0; 42 for(int i=1;i<=n;i++) g[i]=INF; 43 for(int i=0;i<n;i++) 44 { 45 int k=lower_bound(g+1,g+n+1,r_a[i])-g; 46 d2[i]=k; 47 g[k]=r_a[i]; 48 ans2=max(ans2,d2[i]); 49 } 50 51 //枚舉遞增和遞減的分隔點 52 int ans=0; 53 for(int i=0;i<n;i++) 54 { 55 int temp=min(d1[i],d2[n-i-1]); 56 temp=2*(temp-1)+1; 57 if(ans<temp) ans=temp; 58 } 59 printf("%d\n",ans); 60 } 61 return 0; 62 }

UVa 10534 波浪子序列(快速求LIS)