• CF1359D Yet Another Yet Another Task(思维)


    这题题意很清晰,就是求取区间和-区间最大值的最大

    如果我们考虑直接求区间和再减最大值,显然复杂度比较高

    因此考虑枚举每个位置,然后找到以他为最大值的最大区间

    那么答案就是这段区间l-r中,i-r中的前缀和最大值减去l-1-i中前缀和最小值,这就是这段区间的最大和,之后减去当前位置即可

    这种最大最小前缀和可以直接用st表维护表示区间的最大前缀和。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=3e5+10;
    int lg[N];
    int ma[N][21];
    int mi[N][21];
    int sum[N];
    vector<int> num[110];
    int a[N];
    void init(){
        int i;
        lg[1]=0;
        lg[2]=1;
        for(i=3;i<N;i++){
            lg[i]=lg[i>>1]+1;
        }
    }
    int find(int opt,int l,int r){
        if(opt==1){
            int p=lg[r-l+1];
            return min(mi[l][p],mi[r-(1<<p)+1][p]);
        }
        else{
            int p=lg[r-l+1];
            return max(ma[l][p],ma[r-(1<<p)+1][p]);
        }
    }
    int main(){
        init();
        int n;
        cin>>n;
        int i;
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
            num[a[i]+30].push_back(i);
        }
        int j;
        for(j=0;j<21;j++){
            for(i=0;i+(1<<j)-1<=n;i++){
                if(j==0){
                    ma[i][j]=sum[i];
                    mi[i][j]=sum[i];
                }
                else{
                    ma[i][j]=max(ma[i][j-1],ma[i+(1<<(j-1))][j-1]);
                    mi[i][j]=min(mi[i][j-1],mi[i+(1<<(j-1))][j-1]);
                }
            }
        }
        int res=-0x3f3f3f3f;
        for(i=1;i<=n;i++){
            int l=1,r=n;
            for(j=a[i]+1;j<=30;j++){
                int pos=lower_bound(num[j+30].begin(),num[j+30].end(),i)-num[j+30].begin();
                if(pos<(int)num[j+30].size())
                r=min(r,num[j+30][pos]-1);
                if(pos>=1)
                l=max(l,num[j+30][pos-1]+1);
    
            }
            int pre=find(1,l-1,i);
            int nxt=find(2,i,r);
            if(nxt!=pre)
                res=max(res,nxt-pre-a[i]);
        }
        if(res==-0x3f3f3f3f)
            cout<<0<<endl;
        else
            cout<<res<<endl;
    }
    View Code
  • 相关阅读:
    短文本理解蓝图
    BERT在工业界落地的常用三步
    C#:面试相关问题集
    Delphi线程简介Create及其参数、Resume、Suspend和Terminate(转载)
    迭代器模式(学习笔记19)
    备忘录模式(学习笔记21)
    GPS中地面航向角,磁偏角
    访问者模式(学习笔记20)
    easyui:初始化失败的问题
    访问者模式(学习笔记22)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13216727.html
Copyright © 2020-2023  润新知