zoukankan      html  css  js  c++  java
  • 【题解】[Codeforces 1359D] Yet Another Yet Another Task【单调栈 ST 表】

    题目链接

    题意

    给定一序列,求其一个子段,满足该子段的和减去其最大值的结果尽可能大。(nleq 10^5)

    题解

    考虑每个数作为最大值时的最大答案。每个数作为最大值时区间左右端点的范围可以单调栈预处理。于是每次便要查询一段内的最小前缀和和一段内的最大前缀和。ST 表可做(感觉也可以在单调栈的时候一起处理?)。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int getint(){
    	int ans=0,f=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-')f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		ans=ans*10+c-'0';
    		c=getchar();
    	}
    	return ans*f;
    }
    const int N=1e5+10,L=18;
    int a[N],l[N],r[N],s[N],n;
    int smin[L][N],smax[L][N],l2[N];
    void initst(){
        for(int i=0;i<=n;i++)smin[0][i]=smax[0][i]=s[i];
        for(int i=1;i<L;i++){
            for(int j=0;j<=n-(1<<i)+1;j++){
                smin[i][j]=min(smin[i-1][j],smin[i-1][j+(1<<i-1)]);
                smax[i][j]=max(smax[i-1][j],smax[i-1][j+(1<<i-1)]);
            }
        }
    }
    int qmin(int l,int r){
        ++r;
        int t=l2[r-l];
        return min(smin[t][l],smin[t][r-(1<<t)]);
    }
    int qmax(int l,int r){
        ++r;
        int t=l2[r-l];
        return max(smax[t][l],smax[t][r-(1<<t)]);
    }
    int main(){
        n=getint();
        for(int i=1;i<=n;i++)a[i]=getint(),s[i]=s[i-1]+a[i];
        for(int i=2;i<=n;i++)l2[i]=l2[i>>1]+1;
        initst();
    
        a[0]=a[n+1]=0x7f7f7f7f;
        stack<int>stk;
        stk.push(0);
        for(int i=1;i<=n;i++){
            while(a[stk.top()]<=a[i])stk.pop();
            l[i]=stk.top();
            stk.push(i);
        }
        while(stk.size())stk.pop();
        stk.push(n+1);
        for(int i=n;i>=1;--i){
            while(a[stk.top()]<=a[i])stk.pop();
            r[i]=stk.top()-1;
            stk.push(i);
        }
        
        int ans=0;
        for(int i=1;i<=n;i++){
            int s1=qmin(l[i],i-1),s2=qmax(i,r[i]);
            ans=max(ans,s[i-1]-s1 + s2-s[i]);
        }
        
        cout<<ans;
    }
    
    
    知识共享许可协议
    若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
  • 相关阅读:
    webpack 4.X 基础编译
    一个数组中两个数的和为N,找出这两个数字的下标
    Mybatis自动生成,针对字段类型为text等会默认产生XXXXWithBlobs的方法问题
    Docker Mysql
    Docker镜像Push到DockerHub
    E: Unable to locate package git
    linux解压类型总结
    docker安装gitlab
    Docker应用
    解决github访问及上传慢的问题
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/13913240.html
Copyright © 2011-2022 走看看