• HDU 3530 Subsequence


    这道题很有意思,需要巧妙地套用单调队列

    首先我们要明确几件事情

    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。

    代码:


    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    using namespace std;


    typedef pair<int,int> PII;
    const int N=1000010;
    int n,m,k;
    int a[N];
    int ans=0;


    struct MonQ{
        PII q[N];
        int st,ed;
        void clear() {
            st=ed=0;
        }
        void popto(int x){
            while(ed-st>=1 && q[st].second<x) st++;
        }
        void maintain(int mode) {
            if(mode==0) {
                while(ed-st>=2 && q[ed-1]>=q[ed-2]) q[ed-2]=q[ed-1],ed--;
            }else {
                while(ed-st>=2 && q[ed-1]<=q[ed-2]) q[ed-2]=q[ed-1],ed--;
            }
        }
        void push(int x,int p){
            q[ed++]=PII(x,p);
        }
        bool empty(){
            return st==ed;
        }
        int top() {
            if(ed-st>=1) return q[st].first;
            else return 0;
        }
        int label() {
            return q[st].second;
        }
    }q1,q2;


    int main() {
        while(scanf("%d%d%d",&n,&m,&k)!=EOF) {
            for(int i=0;i<n;i++) scanf("%d",&a[i]);
            int st=0;
            ans=0;
            q1.clear();
            q2.clear();
            for(int i=0;i<n;i++) {
                q1.push(a[i],i);
                q2.push(a[i],i);
                q1.maintain(0);
                q2.maintain(1);
                int diff=q1.top()-q2.top();
                if(diff>=m && diff<=k){
                    ans=max(ans,i-st+1);
                }
                while(diff>k && !q1.empty() && !q2.empty()) {
                    int topop=min(q1.label(),q2.label());
                    st=topop+1;
                    q1.popto(st);
                    q2.popto(st);
                    diff=q1.top()-q2.top();
                }

            }
            printf("%d\n",ans);

        }
        return 0;
    }
  • 相关阅读:
    Pixel XL编译和烧录Android 8.0
    公式编辑器CVE-2018-0798样本分析
    CVE-2021-33739 EOP漏洞分析
    Firefox 设置 Burpsuite 代理抓取本地数据包
    前端ECharts框架绘制各种图形
    c 除法反汇编算法
    IDA sig签名批量脚本
    从零构建自己的远控•客户端设计面向对象(13)
    从零构建自己的远控•AES加解密Demo(12)
    从零构建自己的远控•图像切割算法构思(11)
  • 原文地址:https://www.cnblogs.com/programCaiCai/p/HDU3530.html
Copyright © 2020-2023  润新知