SGU 488 Dales and Hills
这给题目和LIS类似,只不过是求连续的单调序列,用单调队列可破之,比如求LDIS(连续单增序列),如果a[i]大于栈顶元素入栈,将top作为序列长度,反过来再扫一遍就是包含该元素的单调递减序列,这样通过LCDS,LCIS函数可得到4个存储某元素左右的单调增,减的数组。然后枚举一遍就可以。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define N 1111111 5 #define INF 0x0f0f0f0f 6 using namespace std; 7 8 int stack1[N];//不要在函数里开大数组!!! 9 int n; 10 void LCIS(int dp[],int a[]) 11 { 12 int top=0; 13 stack1[top]=-INF; 14 for(int i=1;i<=n;i++) 15 { 16 if(a[i]>stack1[top]) 17 { 18 stack1[++top]=a[i]; 19 dp[i]=top; 20 } 21 else top=1,stack1[1]=a[i],dp[i]=top; 22 } 23 } 24 void LDIS(int dp[],int a[]) 25 { 26 int top=0; 27 stack1[top]=INF; 28 for(int i=1;i<=n;i++) 29 if(a[i]<stack1[top]) 30 { 31 stack1[++top]=a[i]; 32 dp[i]=top; 33 } 34 else top=1,stack1[top]=a[i],dp[i]=top; 35 } 36 37 int dp1[N],dp2[N],dp3[N],dp4[N]; 38 int a[N],b[N]; 39 40 int main(void) 41 { 42 int tc; 43 scanf("%d",&tc); 44 while(tc--) 45 { 46 scanf("%d",&n); 47 for(int i=1;i<=n;i++) 48 scanf("%d",a+i),b[n+1-i]=a[i]; 49 LCIS(dp1,a); 50 LCIS(dp2,b); 51 LDIS(dp3,a); 52 LDIS(dp4,b); 53 int ans1=0,ans2=0; 54 for(int i=1;i<=n;i++) 55 { 56 ans1=max(ans1,min(dp1[i]-1,dp2[n+1-i]-1)); 57 ans2=max(ans2,min(dp3[i]-1,dp4[n+1-i]-1)); 58 } 59 printf("%d %d\n",ans1,ans2); 60 } 61 return 0; 62 }