D. Yet Another Yet Another Task (ST表模版 + 单调队列)

Posted -ackerman

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D. Yet Another Yet Another Task (ST表模版 + 单调队列)相关的知识,希望对你有一定的参考价值。

题目链接:https://codeforces.com/contest/1359/problem/D

 

技术图片

 

 

想法:

因为是减去最大值,我们可以考虑直接枚举最大值。

找到左边最后一个 小于等于a[i] 的位置,找到右边最后一个 小于等于a[i] 的位置

找到这样的一个子区间,然后我们利用ST表维护前缀和,找到左边前缀和最小,右边前缀和最大的这样的范围就好了。

 

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <cmath>
#include <cstdio>
#include <iomanip>
#include <ctime>
#include <bitset>
#include <cmath>
#include <sstream>
#include <iostream>

#define ll long long
#define ls nod<<1
#define rs (nod<<1)+1
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define INF 0x3f3f3f3f3f3f3f3f
#define max(a, b) (a>b?a:b)
#define min(a, b) (a<b?a:b)


const double eps = 1e-10;
const int maxn = 2e5 + 10;
const int MOD = 998244353;

int sgn(double a) { return a < -eps ? -1 : a < eps ? 0 : 1; }

using namespace std;


int a[maxn];
int q[maxn];
int f1[maxn],f2[maxn];


int pre[maxn],maxx[maxn][20],minn[maxn][20];
void rmq(int n)
{
    for(int i=0;i<=n;i++) minn[i][0]=maxx[i][0]=pre[i];
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=0;i+j-1<=n;i++)
        {
            maxx[i][j]=max(maxx[i][j-1],maxx[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(maxx[l][k],maxx[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", &a[i]);
        pre[i] = pre[i-1] + a[i];
    }
    rmq(n);
    int cnt;

    // 右边第一个 > a[i] 的数的位置
    q[1] = n + 1;
    cnt = 1;
    a[n + 1] = INF;
    for (int i = n; i >= 1; i--) {
        while (cnt && a[q[cnt]] <= a[i])
            cnt--;
        f1[i] = q[cnt] - 1;
        q[++cnt] = i;
    }
    // 左边第一个 > a[i] 的数的位置
    q[1] = 0;
    cnt = 1;
    a[0] = INF;
    for (int i = 1;i <= n;i++) {
        while (cnt && a[q[cnt]] <= a[i])
            cnt--;
        f2[i] = q[cnt];
        q[++cnt] = i;
    }
//    for (int i = 1;i <= n;i++) {
//        cout << f2[i] << " ";
//    }
//    cout << endl;
    int ans = 0;
    for (int i = 1;i <= n;i++) {
        int l = f2[i],r = f1[i];
        int maxl = q2(l,i-1);
        int maxr = q1(i,r);
        ans = max(ans,maxr - maxl - a[i]);
    }
    printf("%d
",ans);
    return 0;
}

 

以上是关于D. Yet Another Yet Another Task (ST表模版 + 单调队列)的主要内容,如果未能解决你的问题,请参考以下文章

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

Educational Codeforces Round 88 (Rated for Div. 2) D. Yet Another Yet Another Task

Educational Codeforces Round 88 (Rated for Div. 2) D. Yet Another Yet Another Task

D. Yet Another Subarray Problem 思维 难

Educational Codeforces Round 76 (Rated for Div. 2) D. Yet Another Monster Killing Problem 贪心

Educational Codeforces Round 46 D. Yet Another Problem On a Subsequence