HDU 4604 Deque

来源:互联网 发布:压力测试软件 web 编辑:程序博客网 时间:2024/05/20 23:39

题意:给你一个序列,要求你将它从左到右放入一个双向队列中,可以选择放入队尾,队首,或者不放入,求这个队列中最多能放多少个数。

思路:这个队列要最长则必然是以某一点开始的此点右边的最长不上升和最长不下降序列的和再减去重叠的部分。

所以可以先求出每个点右边的最长不上升和最长不下降序列的长度以及每个序列中的重叠部分。再枚举每个点,求出答案。

#include <cstdio>#include <cstring>#include <string>#include <iostream>#include <map>#include <vector>#include <cmath>#include <stack>#include <queue>#include <cstdlib>#include <algorithm>using namespace std;typedef __int64 int64;typedef long long ll;#define M 100005#define inf 0x3f3f3f3f#define mod 1000000007struct node{int down , up;//最长不下降和最长不上升}tp[M];int n , num[M] , dp1[M] , dp2[M] , cnt1[M] , cnt2[M];//cnt1和cnt2分别记录以num[i]为结尾的最长不下降和最长不上升序列的num[i]分别有多少个int Solve(){int i , j , len1 = 1 , len2 = 1;for (i = n ; i > 0 ; i--){cnt1[i] = cnt2[i] = 1;//最长不下降for (j = len1-1 ; j > 0 ; j--){if (num[dp1[j]] <= num[i])break;}if (j == len1-1){if (num[dp1[j]] == num[i])cnt1[i] += cnt1[dp1[j]];dp1[len1++] = i;}else{if (num[dp1[j+1]] == num[i])cnt1[i] += cnt1[dp1[j+1]];dp1[j+1] = i;}tp[i].up = j+1;//最长不上升for (j = len2-1 ; j > 0 ; j--){if (num[dp2[j]] >= num[i])break;}if (j == len2-1){if (num[dp2[j]] == num[i])cnt2[i] += cnt2[dp2[j]];dp2[len2++] = i;}else{if (num[dp2[j+1]] == num[i])cnt2[i] += cnt2[dp2[j+1]];dp2[j+1] = i;}tp[i].down = j+1;}int ret = 0;for (i = 1 ; i <= n ; i++)ret = max(ret,tp[i].down+tp[i].up-min(cnt1[i],cnt2[i]));return ret;}int main(){int t , i;scanf("%d",&t);while (t--){scanf("%d",&n);for (i = 1 ; i <= n ; i++)scanf("%d",num+i);printf("%d\n",Solve());}return 0;}



 

原创粉丝点击