【待完善】HDU - 3530:Subsequence

Subsequence

来源:HDU

标签:数据结构、单调队列

参考资料:

相似题目:

题目

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.

输入

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.

输出

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

输入样例

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

输出样例

5
4

题目大意

一个数字序列,要求找到一个最长的连续子序列,这个子序列的最大值与最小值之差大于等于m,小于等于k。

解题思路

我们要找到一个区间内的最大值和最小值,那么使用两个单调队列,一个为递增队列,一个为递减队列。
挺难理解的,等我详细解释。

参考代码

#include
#include
#define MAXN 100005
using namespace std;

struct Node{
	int v;
	int p;
}up[MAXN],down[MAXN];//递增序列,递减序列 

int n,m,k;
int num[MAXN];

int main(){
	while(~scanf("%d%d%d",&n,&m,&k)){
		for(int i=0;i<n;i++){
			scanf("%d",&num[i]);
		}
		
		int head_d=0, tail_d=0;
		int head_u=0, tail_u=0;
		int ans=0;
		
		int pos=0;
		
		for(int i=0;i<n;i++){
			//递减队列 
			while(head_d<tail_d && num[i]>down[tail_d-1].v) tail_d--;
			down[tail_d].v=num[i]; down[tail_d++].p=i;
			
			//递增队列 
			while(head_u<tail_u && num[i]<up[tail_u-1].v) tail_u--;
			up[tail_u].v=num[i]; up[tail_u++].p=i;
			
			while(down[head_d].v-up[head_u].v>k){//如果最大值-最小值>k 
				if(down[head_d].p<up[head_u].p)//如果最大值的位置 比 最小值的位置 靠前 
					pos=down[head_d++].p+1;//那么应该取 最大值的位置后面 第二个最大值 
				else 
					pos=up[head_u++].p+1;//反之应该取 最小值的位置后面 第二个最小值 
			}
			
			if(down[head_d].v-up[head_u].v>=m){
				ans=max(ans,i-pos+1);
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

你可能感兴趣的:(【记录】算法题解)