• P3512 [POI2010]PIL-Pilots


    题目

    给定n,k和一个长度为n的序列,求最长的最大值最小值相差不超过k的序列

    分析

    可以直接双指针+RMQ来维护,复杂度是 (O(nlogn)) 的(约束RMQ爬)。

    这里讲一个单调队列的思路。

    维护两个单调队列,一个单调上升,一个单调下降。

    然后每加入一个元素先更新两个队列,然后看一下两个队首的差是否大于 (k) ,是的话就弹出两者编号更小的那一个(这里就类似双指针的移动左端点了)

    然后更新答案就是弹出的那一个位置到当前这个位置(没弹出那更好,直接继承上一个答案)。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    #define int long long
    const int N=3e6+5,INF=1e9+7;
    int n,m;
    int a[N],que1[N],hh1=1,tt1,que2[N],hh2=1,tt2;
    inline void cmax(int &x,int y){if(y>x) x=y;}
    signed main(){
    	read(m),read(n);int Ans=0,tmp=1;
    	for(int i=1;i<=n;i++) read(a[i]);
    	hh1=tt1=hh2=tt2=que1[1]=que2[1]=1;
    	for(int i=2;i<=n;i++){
    		while(hh1<=tt1&&a[i]>a[que1[tt1]]) tt1--;
    		while(hh2<=tt2&&a[i]<a[que2[tt2]]) tt2--;
    		que1[++tt1]=i,que2[++tt2]=i;
    		while(a[que1[hh1]]-a[que2[hh2]]>m&&hh1<=tt1&&hh2<=tt2){
    			if(que2[hh2]<que1[hh1]) hh2++,tmp=que2[hh2-1]+1;
    			else hh1++,tmp=que1[hh1-1]+1;
    		} 
    		cmax(Ans,i-tmp+1);
    	}
    	write(Ans);
    	return 0;
    }
    
    

    总结

    这道题的坑点:输入和描述的(n,k)是反着来的..

  • 相关阅读:
    任务栏恢复添加快捷方式(即桌快出现箭头)
    去除桌面快捷方式小箭头
    PHP Warning: date() [function.date]: It is not safe to rely on the system's timezone 转
    坑爹的 mysql error 2003!
    浅谈nvm环境搭建与利用nvm安装nodejs
    本地SVN服务器的搭建(WINDOWS环境)
    DevExpress学习之Gridcontrol
    string 和 StringBuilder 的简单理解!
    关注,被关注!
    C# Using 用法
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14932454.html
Copyright © 2020-2023  润新知