巧妙利用单调队列(12哈工程多校)(3530)
来源:互联网 发布:辐射4xboxonex优化 编辑:程序博客网 时间:2024/05/16 04:36
Subsequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5495 Accepted Submission(s): 1809
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.
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 01 1 1 1 15 0 31 2 3 4 5
Sample Output
54
这道题很有意思,需要巧妙地套用单调队列
首先我们要明确几件事情
1.假设我们现在知道序列(i,j)是符合标准的,那么如果第j+1个元素不比(i,j)最大值大也不比最小值小,那么(i,j+1)也是合法的
2.如果(i,j)不合法的原因是差值比要求小,那在(i,j)范围内的改动是无效的,需要加入j+1元素充当最大值或者最小值才可能获得合法的序列
3.假设序列(i,j)的差值比要求大,那么我们必须将其中的最大值或者最小值从序列中删除出去,才可能获得一个合法的序列,只往里加入元素是不可能令序列合法的
基于以上几点考虑,我们可以利用单调队列完成我们的算法。
设定一个变量ST作为当前合法序列的开端(对于一个序列(i,j),其对应的ST为i-1),初始值是0
设f[i]是以第i个元素结尾的最长合法序列长度,我们把i加入两个单调队列中维护,一个维护i之前的最小值,一个是最大值。
情况1.如果最大值和最小值的差值在范围之内,那么(ST,i)是合法序列,f[i]=i-ST。
情况2.如果差值比要求小,则没有以i结尾的合法序列,f[i]=0。
情况3.如果差值比要求大,那么需要删除最大值或者最小值,怎么删除?当然是删除最大值和最小值中靠前的那个,同时ST相应更新,直到情况1或者情况2。
理解:理解的难点在于每次加入新元素的时候对于两个单调队列的处理:ST是记录当前合法序列的开始的地方(ST这个临时变量很关键!!),每次求的其实都是从i开始向前的连续最大长度,单调队列维护的是i之前的最大值和最小值。(一开始想不通的点:如果前一个把D2全更新掉了,即前一个元素最大,对后一个元素产生的影响:无影响,因为从i向前必须得算上这个最大的元素,如果不行,那么避免不了,如果行,ST的值也不会随意变动)/*------------------Header Files------------------*/#include <iostream>#include <cstring>#include <string>#include <cstdio>#include <algorithm>#include <cstdlib>#include <ctype.h>#include <cmath>#include <stack>#include <queue>#include <deque>#include <map>#include <vector>#include <limits.h>using namespace std;/*------------------Definitions-------------------*/#define LL long long#define PI acos(-1.0)#define INF 0x3F3F3F3F#define MOD 10E9+7#define MAX 500050/*---------------------Work-----------------------*/int D1[100010],D2[100010],f[100010];void work(){int n,m,k;while(scanf("%d%d%d",&n,&m,&k)==3){int L1,L2,ST,R1,R2,ans;ans=L1=L2=ST=0,R1=R2=-1;for(int i=1;i<=n;i++){scanf("%d",&f[i]);while(L1<=R1&&f[D1[R1]]>=f[i]) R1--; //D1从小到大//把比它大的数都更新掉D1[++R1]=i;while(L2<=R2&&f[D2[R2]]<=f[i]) R2--; //D2从大到小//把比它小的数都更新掉D2[++R2]=i;while(f[D2[L2]]-f[D1[L1]]>k){if(D1[L1]<D2[L2]){ST=D1[L1];L1++;}else{ST=D2[L2];L2++;}}if(f[D2[L2]]-f[D1[L1]]>=m&&ans<i-ST) ans=i-ST;}printf("%d\n",ans);}}/*------------------Main Function------------------*/int main(){//freopen("test.txt","r",stdin);//freopen("cowtour.out","w",stdout);//freopen("cowtour.in","r",stdin);work();return 0;}
0 0
- 巧妙利用单调队列(12哈工程多校)(3530)
- HDU 3530 单调队列
- HDU 3530 单调队列
- hdu~3530(单调队列)
- HDU 3530 单调队列
- HDU 3530 Subsequence 【单调队列】
- hdu 3530 Subsequence //单调队列
- hdu 3530 单调队列dp
- hdu 3530 Subsequence 单调队列
- Hdu 3530 Subsequence 单调队列
- hdu 3530 Subsequence(单调队列)
- hdu 3530(双单调队列)
- HDU 3530 Subsequences(单调队列)
- hdoj--3530 Subsequence(单调队列)
- 单调队列 HDU 3530 Subsequence
- hdu 3530 Subsequence 单调队列
- hdu 3530 Subsequence 单调队列
- HDU - 3530 Subsequence 单调队列
- POJ 2155 Matrix(二维树状数组)
- 启动画面的细节处理
- 使用axis调用webservice
- linux系统从简单命令到熟练掌握
- matlab和C++混编(1)配置开发环境
- 巧妙利用单调队列(12哈工程多校)(3530)
- 安卓开发常见问题
- 速e平台列表日期显示格式设置
- maven+eclipse基础
- C++ 多线程并发控制——互斥锁 pthread_mutex
- 二分查找算法----递归&&非递归
- POJ2551 & UVA 10127 Ones (数论) 计算至少要多少位十进制的1能够被n整除
- Longest Substring Without Repeating Characters
- visual c++ 中的stdafx.h头文件的作用