HDU 3530 单调队列

 

/*
copy的题意:给出一个序列,求最长的连续子序列,使得 M<=Max-Min<=K
    n <= 10^5
    一开始我把Max-Min合起来弄,搞不出
    然后看了别人说用两个单调队列,一个存单调递减,一个存单调递增
    想了下细节,1y,有点惊奇..

    我知道单调队列可以快速知道i及之前的最大/小值,这道题分开两个队列来做很好!!

    Max - Min 为两个队列的队首之差
    while(Max-Min>K) 看哪个的队首元素比较前就移动谁的

    最后求长度时,需要先记录上一次的被淘汰的最值位置last ,这样[last+1,i]即为满足条件的连续子序列了
    i - last
*/
# include<iostream>
# include<stdio.h>
# include<string.h>
using namespace std;
inline int Max(int a,int b){return a>b?a:b;}
#define N 1001000

int Q1[N], Q2[N];//Q1递增  单调队列就是存储序列中最大值,次最大值等的位置(存的是下标,以便可以快速访问对应数字)
int front1, front2;
int rear1,  rear2;
int sum[N];

int main()
{
   int n,k,m;
   while(~scanf("%d%d%d",&n,&m,&k))
   {
	   front1 = front2 = 0;
	   rear1  = rear2  = 0;
	   int last1 = 0, last2 = 0;
	   int ans = 0;
	   for(int i = 1; i<= n;i++){
		   scanf("%d",&sum[i]);
		   while(front1<rear1 && sum[ Q1[rear1-1] ]>=sum[i]) rear1--;
		   Q1[rear1++] = i;

		   while(front2<rear2 && sum[ Q2[rear2-1] ]<=sum[i]) rear2--;
		   Q2[rear2++] = i;

		   while(sum[ Q2[front2] ] - sum[ Q1[front1] ] > k )//序列尾部向前靠拢
		   {
			   if(Q1[front1]>Q2[front2])
				   last2 = Q2[front2++];
			   else
				   last1 = Q1[front1++];
		   }
		   if(sum[ Q2[front2] ] - sum[ Q1[front1] ] >= m)
			   ans = Max(ans, i-Max(last1, last2));
	   }
	   printf("%d\n",ans);
   }
   return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值