题意:给定一个序列,从前往后取,然后给出一个可以从前面加和从后面加的特殊栈,但是这个栈必须保持递增,问你栈的最长长度为多少
解题思路:从后往前枚举第一个加入栈的队列,在求从后同时求不递增,不递减序列,然后在序列中找最小重复的,对于这个点的最大长度就是两个长度相加再减去最小重复的。
解题思路:
// File Name: e.c // Author: darkdream // Created Time: 2013年07月25日 星期四 10时17分58秒 #include<stdio.h> #include<string.h> #include<stdlib.h> #include<time.h> #include<math.h> #include<ctype.h> int a[100005]; int stackup[100005]; int stacklow[100005]; int ans[100005]; int toplow = 0 ; int topup = 0 ; int update(int stack[],int top,int temp) { int low = 1; while(low <= top) { int mid = (low + top) / 2; if(temp >= stack[mid]) { low = mid + 1; } else { top = mid - 1; } } return low; } int find(int stack[],int top,int temp) { int low = 1 ; while(low <= top) { int mid = (low + top)/2; if(stack[mid] < temp ) { low = mid + 1; } else { top = mid - 1 ; } } return top; } int main() { //freopen("1005.in","r",stdin); //freopen("/home/plac/problem/output.txt","w",stdout); int t ; scanf("%d",&t); while(t--) { int n ; int max = 0 ; memset(stackup,0,sizeof(stackup)); memset(stacklow,0,sizeof(stacklow)); memset(a,0,sizeof(a)); memset(ans,0,sizeof(ans)); scanf("%d",&n); toplow = 0 ; topup = 0 ; for(int i =1 ; i<= n; i ++) scanf("%d",&a[i]); int ans1 , ans2 ; for(int i = n; i >= 1 ; i --) { int l1,l2 ; if(a[i] >= stackup[topup] ) { topup ++ ; stackup[topup] = a[i]; ans1 = topup; } else { int r = update(stackup,topup,a[i]); stackup[r] = a[i]; ans1 = r; //printf("%d ",r); } l1 =ans1 - find(stackup,ans1,a[i]) - 1; if((-a[i]) >= stacklow[toplow] || !toplow ) { toplow ++ ; stacklow[toplow] = -a[i]; ans2 = toplow; } else { int r = update(stacklow,toplow,-a[i]); stacklow[r] = -a[i]; ans2 = r; } l2 =ans2 - find(stacklow,ans2,-a[i]) - 1; // printf("%d %d *** %d %d ",l1,l2,ans1,ans2); if(ans2 - l2 + ans1 > ans1 - l1 + ans2) ans[i] = ans2 - l2 + ans1 - 1; else ans[i] = ans1 - l1 + ans2 - 1; } for(int i = 1; i <= n; i ++) if(ans[i] > max ) max = ans[i]; printf("%d ",max); } return 0 ; }