题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1879 Accepted Submission(s): 689
1 #include<cstdio> 2 #include<cstring> 3 int a[100010],z[100010],j[100010],zm[100010],jm[100010]; 4 // z中存的是以i个数起始的最长递增子序列的最大长度,j中存的递减子序列的长度,zm长度为i的递增序列的初始项,jm递减序列的初始项 5 int lz,lj; 6 void findzeng(int index,int x,int l)//找到大于x的子序列,zm单调减 7 { 8 int f,t,h=l; 9 /* if(x>zm[1]) 10 { 11 z[index]=1; 12 zm[1]=x; 13 } */ 14 f=1; 15 while(f<=h)//二分法查找 16 { 17 t=(f+h)/2; 18 if(x<=zm[t])f=t+1; 19 else h=t-1;//x>zm[t]的情况 20 } 21 z[index]=f; 22 if(f>lz) 23 { 24 lz=f; 25 zm[f]=x; 26 } 27 else if(x>zm[f]) 28 zm[f]=x; 29 } 30 void findjian(int index,int x,int l) 31 { 32 int f,t,h=l; 33 f=1; 34 while(f<=h)//j[n]单调增 35 { 36 t=(f+h)/2; 37 if(x>=jm[t]) 38 f=t+1; 39 else 40 h=t-1; 41 } 42 j[index]=f; 43 if(f>lj) 44 { 45 lj=f; 46 jm[f]=x; 47 } 48 else if(jm[f]>x) 49 jm[f]=x; 50 } 51 int main() 52 { 53 // freopen("1.in","r",stdin); 54 int t,n,i,maxl,temp,k; 55 scanf("%d",&t); 56 while(t--) 57 { 58 maxl=0; 59 scanf("%d",&n); 60 for(i=1;i<=n;i++) 61 scanf("%d",&a[i]); 62 memset(zm,0,sizeof(zm)); 63 memset(jm,0,sizeof(jm)); 64 z[n]=1;j[n]=1; 65 zm[1]=a[n];jm[1]=a[n]; 66 lz=1;lj=1; 67 for(i=n-1;i>0;i--) 68 { 69 findzeng(i,a[i],lz); 70 findjian(i,a[i],lj); 71 } 72 for(i=1;i<=n;i++) 73 { 74 if(maxl>=n-i+1) 75 break; 76 temp=z[i]+j[i]-1; 77 k=1; 78 while(z[i]-k>0&&zm[z[i]]==zm[z[i]-k]) 79 { 80 temp-=1;k++; 81 } 82 if(temp>maxl) 83 maxl=temp; 84 } 85 printf("%d\n",maxl); 86 } 87 return 0; 88 }