Educational Codeforces Round 88 (Rated for Div. 2)D. Yet Another Yet Another Task(ST表+单调栈)

题目:click
题意:找到一段区间的总和减该区间的最大值的最大值。

一开始想的是dp找最大的连续子序列的MAX减该段的MAX,仔细一想可以发现问题,这个思路是不对的,我们考虑先去把a[i]看做是该区间的最大值,进行枚举处理,单调队列确定该区间的端点,SUM数组去做前缀和。直接减吗?进一步思考可以发现是错误的。。。可能边缘全是负数我们并不需要,直接用ST表去维护一个区间的max和min,找到[i,r]区间和最大的,减去[l,i-1]区间和最小的得最大值。注意一下细节,st表从0开始。

#include<cmath>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cstdlib>
#include<istream>
#include<vector>
#include<stack>
#include<set>
#include<map>
#include<algorithm>
#include<queue>
#define inf 0x3f3f3f3f
#define llinf 0x3f3f3f3f3f3f3f3f
#define MAX_len 200005*4
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
int n;
int a[100100];
int LMAX[100100],RMAX[100100];
int que[100100];
int SUM[100100];
int stmax[100100][20];
int stmin[100100][20];
void init(int n)
{
	int i,j,k;
    for(i=0;i<=n;i++)
	stmax[i][0]=stmin[i][0]=SUM[i];
    int t=log2(n)+1;
    for(int j=1;j<t;j++)
	{
        for(int i=0;i<=n-(1<<j)+1;i++)
		{
            stmax[i][j]=max(stmax[i][j-1],stmax[i+(1<<(j-1))][j-1]);
            stmin[i][j]=min(stmin[i][j-1],stmin[i+(1<<(j-1))][j-1]);
        }
    }
}
int solvemax(int l,int r)
{
    int k=log2(r-l+1);
    return max(stmax[l][k],stmax[r-(1<<k)+1][k]);
}
int solvemin(int l,int r)
{
	int k=log2(r-l+1);
	return min(stmin[l][k],stmin[r-(1<<k)+1][k]);
}
int main()
{
    scanf("%d",&n);
    int i,j,k;
    SUM[0]=0;
    int ans=0;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        SUM[i]=SUM[i-1]+a[i];
    }
        init(n);
        int h=1,t=0;
    for(i=1;i<=n;i++)
    {
        while(h<=t&&a[que[t]]<=a[i])
        {
            t--;
        }
        if(h<=t)
            LMAX[i]=que[t];
        else
            LMAX[i]=0;
        que[++t]=i;
    }
    h=1,t=0;
    for(i=n;i>=1;i--)
    {
        while(h<=t&&a[que[t]]<=a[i])
        {
            t--;
        }
        if(h<=t)
            RMAX[i]=que[t]-1;
        else
            RMAX[i]=n;
        que[++t]=i;
    }
    for(i=1;i<=n;i++)
    {
        int l=LMAX[i];
        int r=RMAX[i];
        ans=max(ans,solvemax(i,r)-solvemin(l,i-1)-a[i]);
    }
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43958964/article/details/106439779