HDU 3530 Subsequence(单调队列)

Problem Description

There is a sequence of integers. Your task is to find the longest subsequence that satisfies the following condition: the difference between the maximum element and the minimum element of the subsequence is no smaller than m and no
larger than k.

Input

There are multiple test cases.

For each test case, the first line has three integers, n, m and k. n is the length of the sequence and is in the range [1, 100000]. m and k are in the range [0, 1000000]. The second line has n integers, which are all in the range [0, 1000000].

Proceed to the end of file.

Output

For each test case, print the length of the subsequence on a single line.

Sample Input

5 0 0
1 1 1 1 1
5 0 3
1 2 3 4 5

Sample Output

5
4

Source

思路:两个队列,一个维护最大值,一个维护最小值,当i分别如两个队列时,如果最大值减最小值大于k,那么两个队列最小的出队,此时需要记录他的位置,因为他的下一个位置就是满足条件的最小的pos,

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>

#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define MID(x,y) ((x+y)>>1)

#define eps 1e-8
typedef __int64 ll;

#define fre(i,a,b)  for(i = a; i <b; i++)
#define free(i,b,a) for(i = b; i >= a;i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define ssf(n)      scanf("%s", n)
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define bug         pf("Hi\n")

using namespace std;

#define INF 0x3f3f3f3f
#define N 100005

int n,m,k;
int a[N],mique[N],maque[N];
int mitail,mihead,matail,mahead;
int now;

void miinque(int i)
{
	while(mihead<mitail&&a[i]<a[mique[mitail-1]])
	  mitail--;
	mique[mitail++]=i;
}

void mainque(int i)
{
	while(mahead<matail&&a[i]>a[maque[matail-1]])
		matail--;
	maque[matail++]=i;
}

void outque()
{
     while(a[maque[mahead]]-a[mique[mihead]]>k)
		if(maque[mahead]>mique[mihead])
		  {
		  	now=mique[mihead];  //满足条件的最小的pos-1
		  	mihead++;
		  }
	    else
		  {
		  	now=maque[mahead];  ////满足条件的最小的pos-1
		  	mahead++;
		  }
}

int main()
{
	int i,j,ans;
	while(~sfff(n,m,k))
	{
		fre(i,1,n+1)
		 sf(a[i]);

		mitail=mihead=matail=mahead=0;

		ans=0;
        now=0;

		fre(i,1,n+1)
		{
			miinque(i);
			mainque(i);
			outque();
			if(a[maque[mahead]]-a[mique[mihead]]>=m)
			 {
			 	ans=max(ans,i-now);
			 }

		}
        pf("%d\n",ans);
	}
	return 0;
}
时间: 2024-08-14 09:44:09

HDU 3530 Subsequence(单调队列)的相关文章

hdu 3530 (单调队列)

Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4441    Accepted Submission(s): 1457 Problem Description There is a sequence of integers. Your task is to find the longest subsequenc

HDU 3530 Subsequences(单调队列)

解题思路: 开两个单调队列即可. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <set> #include <map>

hdu3530 Subsequence 单调队列

// hdu3530 Subsequence 单调队列 // 题目大意:找到一个最大的子串,使得子串区间内最大值和最小值的差 // 在low和up范围内,串的规模10w. // 解题思路: // 单调队列,单调队列可以保留i位置之前的最大值和最小值的下标,有了这些 // 则,每次我们比较两个队列的队头,看差值是否大于up,(因为它是到i位置最大 // 的差值,其他值不可能比i还要大.) // 如果大于,则将两个对头靠前的那个丢掉,即出队,再比较对头,并且记录下 // 出队的位置下标,(因为此时出

hdu 3530 Subsequence

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3530 Subsequence Description There is a sequence of integers. Your task is to find the longest subsequence that satisfies the following condition: the difference between the maximum element and the minim

HDU 3401 Trade(单调队列优化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3401 题意:炒股.第i天买入一股的价钱api,卖出一股的价钱bpi,最多买入asi股,最多卖出bsi股.两次操作(买入或卖出)中间必须相差W天.炒股时间为n.任意时间手中的股票不大于MaxP.求最大收益. dp[i][j]代表第i天手上有j股的最大收益,dp[i][j]=max(dp[i-1][j],dp[i-W][k]+(j-k)*ap[i],dp[i-W][k]+(k-j)*bp[i]); dp

HDU 5289 Assignment(单调队列)

Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 297    Accepted Submission(s): 152 Problem Description Tom owns a company and he is the boss. There are n staffs which are numbered fro

hdu 2430 Beans 单调队列

#include<iostream> #include<cstdio> #include<vector> #include<cstring> #include<string> #include<algorithm> #include<queue> #include<cmath> using namespace std; //题意:从num[1]~num[n]中取一段连续的序列,使得(num[i]+...+num

HDU 3530 Subsequence (dp+单调队列)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3530 题意: 找一个最长的区间,区间最大值与最小值的差 大于等于小于等于k 分析: 维护最大值与最小值,然后最大的最大值与最小的最小值的差是不是大于y,大于y谁在前面删除谁,记录起点. 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #inc

hdu 4374 (单调队列+dp)

d[i][j]表示i行j列格子可以得到的最大值 顺着来的时候 d[i][j]=max(d[i-1][k]+sum[k...j])=max(d[i-1][k]-sum[1..k-1]+sum[1...j])  sum[1...j]是固定值 只要找d[i-1][k]+sum[1...k]  的最大值就可以了 找法就是维护一个单调递减的队列,每次加入一个值进去就把队列值后面小于它的点都删掉,把前面j-k>t的点删掉(走的步数大于t步),d[i][j]=队首值+sum[1...j] 逆着来的时候 d[i