• 【CF-1359 D. Yet Another Yet Another Task】 ST表+单调队列


    D. Yet Another Yet Another Task

    题意

    给出一个长度为(n)的整数数组,让找出一个连续子序列,它的和减去最大值是最大的。

    思路

    我写的代码有点多了。。。

    ST表+单调队列。

    因为是减去最大值,所以我们可以枚举每个数字作为最大值。

    左边第一个大于它的数字到右边第一个大于它的数字,这个开区间所有包含最大值的

    子区间,都可以被选择。用单调队列求出来左边第一个大于它的位置,右边同理。

    那么在左边选择一个前缀和最小的,右边选择一个前缀和最大的,计算出区间和之后减去当前值。

    使用ST表维护前缀和。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+10;
    typedef long long ll;
    typedef unsigned long long ull;
    
    int arr[N],pre[N],maxn[N][20],minn[N][20];
    int lmax[N],rmax[N];
    int que[N],h,t;
    void rmq(int n)
    {
        for(int i=0;i<=n;i++) minn[i][0]=maxn[i][0]=pre[i];
        for(int j=1;(1<<j)<=n;j++)
        {
            for(int i=0;i+j-1<=n;i++)
            {
                maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
                minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
            }
        }
    }
    int q1(int l,int r)
    {
        int k=0,dis=r-l+1;
        while((1<<(k+1))<=dis) ++k;
        return max(maxn[l][k],maxn[r-(1<<k)+1][k]);
    }
    int q2(int l,int r)
    {
        int k=0,dis=r-l+1;
        while((1<<(k+1))<=dis) ++k;
        return min(minn[l][k],minn[r-(1<<k)+1][k]);
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&arr[i]);
            pre[i]=pre[i-1]+arr[i];
        }
        rmq(n);
        h=1,t=0;
        for(int i=1;i<=n;i++)
        {
            while(h<=t&&arr[que[t]]<=arr[i]) t--;
            if(h<=t) lmax[i]=que[t];
            else lmax[i]=0;
            que[++t]=i;
        }
        h=1,t=0;
        for(int i=n;i;i--)
        {
            while(h<=t&&arr[i]>=arr[que[t]]) t--;
            if(h<=t) rmax[i]=que[t]-1;
            else rmax[i]=n;
            que[++t]=i;
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            int l=q2(lmax[i],i-1),r=q1(i,rmax[i]);
            ans=max(ans,r-l-arr[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Idea的类中使用实体类(有@Data注解)的Get/Set方法报错
    Springboot前后端分离中,后端拦截器拦截后,前端没有对应的返回码可以判断
    Window NodeJs安装
    Linux(CENTOS7) NodeJs安装
    Linux(CENTOS7) YUM方式安装mysql5.7
    根据M3U8地址下载视频
    Mysql时间范围分区(RANGE COLUMNS方式)
    Window Mysql5.7免安装版配置
    Window Jdk配置(win7/win10都可以)
    .net core2.0 读取appsettings.json
  • 原文地址:https://www.cnblogs.com/valk3/p/12989896.html
Copyright © 2020-2023  润新知