1. 程式人生 > >“盛大遊戲杯”第15屆上海大學程序設計聯賽夏季賽暨上海高校金馬五校賽 F

“盛大遊戲杯”第15屆上海大學程序設計聯賽夏季賽暨上海高校金馬五校賽 F

con text mes namespace view spa label 子序列 cti

如果一個序列有奇數個正整數組成,不妨令此序列為a 1 ,a 2 ,a 3 ,...,a 2?k+1 (0<=k ),並且a 1 ,a 2 ...a k+1 是一個嚴格遞增的序列,a k+1 ,a k+2 ,...,a 2?k+1 ,是一個嚴格遞減的序列,則稱此序列是A序列。

比如1 2 5 4 3就是一個A序列。

現在Jazz有一個長度為n 的數組,他希望讓你求出這個數組所有滿足A序列定義的子序列裏面最大的那個長度。(子序列可以不連續)

比如1 2 5 4 3 6 7 8 9,最長的A序列子串是1 2 5 4 3。

多組輸入,每組兩行。
第一行是n ,表示給的數組的長度。
第二行有n

個數(int範圍),即給你的數組。
1<=n<=500000

每組輸入輸出一行,即最長的A序列子串的長度。

復制
9
1 2 5 4 3 6 7 8 9
5

解法:
1 要求應該是對稱形式,左升右降
2 當然要用LIS
3 我們對每一個點當做最高點,看從左和從右最長能到多少
3 因為是對稱,那麽最大值不要,我們用最小的,比如從左邊開始最長是5,右邊是3,那麽我們選3(左邊能到5,到3沒問題)
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using
namespace std; 4 const int maxn=500005; 5 int a[maxn]; 6 int b[maxn],c[maxn],d[maxn],e[maxn]; 7 int Search(int num,int low,int high){ 8 int mid; 9 while(low<=high){ 10 mid=(low+high)/2; 11 if(num>b[mid]) low=mid+1; 12 else high=mid-1; 13 } 14 return low;
15 } 16 void DP(int n,int* x,int a[]) 17 { 18 int i,len,pos; 19 b[1]=a[1]; 20 x[1]=1; 21 len=1; 22 for(i=2;i<=n;i++) 23 { 24 if(a[i]>b[len])//如果a[i]比b[]數組中最大還大直接插入到後面即可 25 { 26 len=len+1; 27 b[len]=a[i]; 28 pos=len; 29 } 30 else//用二分的方法在b[]數組中找出第一個比a[i]大的位置並且讓a[i]替代這個位置 31 { 32 pos=Search(a[i],1,len); 33 b[pos]=a[i]; 34 } 35 x[i]=pos; 36 } 37 } 38 int main(){ 39 int n; 40 while(~scanf("%d",&n)){ 41 for(int i=1;i<=n;++i) {scanf("%d",&a[i]);e[i]=a[i];} 42 reverse(e+1,e+n+1); 43 DP(n,c,a); 44 memset(b,0,sizeof(b)); 45 DP(n,d,e); 46 int Maxlen=-1; 47 reverse(d+1,d+n+1); 48 for(int i=1;i<=n;i++){ 49 int ans=min(c[i],d[i]); 50 Maxlen=max(Maxlen,2*ans-1); 51 } 52 printf("%d\n",Maxlen); 53 } 54 return 0; 55 }

“盛大遊戲杯”第15屆上海大學程序設計聯賽夏季賽暨上海高校金馬五校賽 F