1 条题解
-
0
自动搬运
来自洛谷,原作者为

alksdjhfg
None搬运于
2025-08-24 21:49:41,当前版本为作者最后更新于2017-08-08 09:24:41,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
n<=3000000,单调队列。
因为要同时维护最大值和最小值,所以需要两个单调队列,记录序号和最大最小值,然后
从左往右枚举一遍O(n)的复杂度即可。
单调队列的实现以最大值为例,当队列非空且队尾的数没有现在枚举到的这个数大时,就
让队尾的数出队,因为在接下来的情况中它们永远不会是一个区间的最大值。最小值的队列同理。把当前位置加入最大最小值队列。然后比较最大值队列的队首即最大值和最小值,如果它们的差超过了k,就看一下最大值和最小值的队首哪个的序号更小,让序号更小的出队,同时更新当前队列的最前节点的位置,继续比较两个的队首,直到最大最小值的差小于等于k时,用当前位置减去当前队列的最前节点的位置再加一,就是目前的符合条件的序列长度,与最长值比较即可。
当前队列的最前节点的位置初始值为1.
代码如下:
#include<iostream> #include<cstdio> using namespace std; #define ll long long ll k,n,a[3000005],q_mx[3000005],q_mn[3000005]; ll head_mx,head_mn,tail_mx,tail_mn,len,pre; int main(){ // freopen("1.in","r",stdin); scanf("%lld%lld",&k,&n); len=0; for(int i=1;i<=n;i++)scanf("%lld",&a[i]); q_mx[1]=1;q_mn[1]=1;pre=1; head_mx=1;tail_mx=1;head_mn=1;tail_mn=1; for(int i=2;i<=n;i++){ while(head_mx<=tail_mx&&a[q_mx[tail_mx]]<a[i])tail_mx--; while(head_mn<=tail_mn&&a[q_mn[tail_mn]]>a[i])tail_mn--; q_mx[++tail_mx]=i;q_mn[++tail_mn]=i; while(a[q_mx[head_mx]]-a[q_mn[head_mn]]>k){ if(q_mx[head_mx]<q_mn[head_mn]){pre=q_mx[head_mx]+1;head_mx++;} else {pre=q_mn[head_mn]+1;head_mn++;} } //pre=min(q_mx[head_mx],q_mn[head_mn]); len=max(len,i-pre+1); } printf("%lld",len); }
- 1
信息
- ID
- 2588
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者