• 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)是反着来的..

  • 相关阅读:
    git常用指令 github版本回退 reset
    三门问题 概率论
    如何高效的学习高等数学
    数据库6 关系代数(relational algebra) 函数依赖(functional dependency)
    数据库5 索引 动态哈希(Dynamic Hashing)
    数据库4 3层结构(Three Level Architecture) DBA DML DDL DCL DQL
    梦想开始的地方
    java String字符串转对象实体类
    java 生成图片验证码
    java 对象之间相同属性进行赋值
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14932454.html
Copyright © 2020-2023  润新知