首页 > 其他 > 详细

[POI2010]PIL-Pilots

时间:2019-11-07 22:07:34      阅读:82      评论:0      收藏:0      [点我收藏+]

洛咕

题意:给定一个长度为\(n(n<=1e6)\)的序列,求最长的最大值与最小值相差不超过\(k\)的序列的长度.

分析:维护两个单调队列,一个维护最大值,一个维护最小值,转移之前判断如果最大值减最小值超过\(k\),哪边的队头下标小就清除哪边的队头,同时记录一下踢出的队头的最大值\(last\),那么此时\([last+1,i]\)就是一段合法的区间.这里就能解释为什么哪边的队头下标小就清除哪边的队头了,因为我们要保证长度最长,所以\(last\)越小越好.

\(O_2\)玄学\(RE???\)没救了.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=1e6+5;
int k,n,a[N],q1[N],q2[N];
int main(){
    k=read();n=read();for(int i=1;i<=n;++i)a[i]=read();
    int l1=1,r1=0,l2=1,r2=0,ans=0,last=0;
    for(int i=1;i<=n;++i){
        while(l1<=r1&&a[i]>a[q1[r1]])--r1;q1[++r1]=i;
        while(l2<=r2&&a[i]<a[q2[r2]])--r2;q2[++r2]=i;
        while(a[q1[l1]]-a[q2[l2]]>k){
            if(q1[l1]<q2[l2])last=max(last,q1[l1]),++l1;
            else if(q1[l1]>q2[l2])last=max(last,q2[l2]),++l2;
        }
        ans=max(ans,i-last);
    }
    printf("%d\n",ans);
    return 0;
}

[POI2010]PIL-Pilots

原文:https://www.cnblogs.com/PPXppx/p/11815760.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!