您的位置:首页 > 产品设计 > UI/UE

HDU 3530 Subsequence 【单调队列】

2010-08-17 03:06 369 查看
【题目地址】
http://acm.hdu.edu.cn/showproblem.php?pid=3530
【题目大意】

给定一个数列,长度n(1<=n<=100000), 值m和k, 求最长子序列,满足当中的最大值-最小值差不小于m且不大于k。

【解题思路】

朴素的O(n^3)的算法很容易想到,但是显然会超时。

假设当前枚举区间起点i,维护i到j之间的最大值和最小值,可以得到O(n^2)的算法,仍然超时。

用两个单调队列(一个递减,一个递增)来维护区间最小值和最大值。

假设now为区间起始点,枚举到i时,两个队列队头保留的是now到i的最大值和最小值。

当两个队头元素的差大于k时,删除其中一个队列队头,now要变大。

我们同时记录队列中元素的在数列中的下标,删除两个队头下标小的元素,now更新为该元素的下一个。

做了删除之后,判断队头元素的差是否条件,如果满足,那么当前能得到一个序列,长度为i-now+1,找出最大的一个即可。

PS:据说上述O(n^2)的算法,优化后也可以AC。

【代码】

#include<cstdio>
#define maxn 100010
struct Dq {
int val,pos;
}q1[maxn],q2[maxn],temp;
int main()
{
int n,m,k,i,h1,h2,t1,t2,now,ans;
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
h1=h2=now=ans=0;
t1=t2=-1;
for(i=0;i%d",&temp.val),temp.pos=i;
while(h1<=t1&&q1[t1].val<=temp.val)
t1--;
q1[++t1]=temp;
while(h2<=t2&&q2[t2].val>=temp.val)
t2--;
q2[++t2]=temp;
while(q1[h1].val-q2[h2].val>k){
if(q1[h1].poselse {
now=q2[h2].pos+1;h2++;
}
}
if(q1[h1].val-q2[h2].val<=k&&q1[h1].val-q2[h2].val>=m)
ans=ans>i-now+1?ans:i-now+1;
}
printf("%d/n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: