【题解】 CF1359D 【Yet Another Yet Another Task】

The scan line boss is really strong...

Let me talk about my strange approach.

According to the meaning of the question, as long as you first select an interval, the maximum value must be removed, then we can consider enumerating the maximum value removed.

So considering each number as the range that the maximum value can affect, it is obvious that the monotonic stack can be used to find the first one on the left and right that is larger than it.

KI iii is in[l, r] [l,r][l,r ] is the maximum value, then we have to start from this position and find a segment and the largest sub-segment from left to right respectively.

Consider the right side first, and the left side is the same. We prefix and sum the original sequence, then we have to find [i, r] [i,r][i,The maximum value of the prefix sum in r ] . So we use the st table to preprocess and query the maximum value of the interval.

For the convenience of the code, two arrays are opened to handle the left and right situations respectively.

#include <bits/stdc++.h>
#define MAX 100005
using namespace std;

int n;
int a[MAX], lg[MAX];

struct solve{
    
    
    int s[MAX], st[MAX][22], r[MAX], q[MAX];

    int query(int l, int r){
    
    
        int len = lg[r-l+1];
        return max(st[l][len], st[r-(1<<len)+1][len]);
    }

    void build(int *a){
    
    
        memset(s, 0, sizeof(s));
        for(int i = 1; i <= n; i++){
    
    
            s[i] = st[i][0] = s[i-1]+a[i];
        }
        for(int j = 1; j <= 19; j++){
    
    
            for(int i = 1; i+(1<<j-1) <= n; i++){
    
    
                st[i][j] = max(st[i][j-1], st[i+(1<<j-1)][j-1]);
            }
        }
        int top = 0;
        for(int i = 1; i <= n; i++){
    
    
            while(top && a[q[top]] < a[i]) r[q[top]] = i, top--;
            q[++top] = i;
        }
        for(int i = 1; i <= top; i++){
    
    
            r[q[i]] = n+1;
        }
    }
}s1, s2;

int main()
{
    
    
    cin >> n;
    lg[0] = -1;
    for(int i = 1; i <= n; i++){
    
    
        scanf("%d", &a[i]);
        lg[i] = lg[i/2]+1;
    }

    s1.build(a);
    reverse(a+1, a+n+1);
    s2.build(a);
    int ans = (int)-1e9;
    for(int i = 1; i <= n; i++){
    
    
        int p1 = i, p2 = n-p1+1;
        int t1 = s1.query(p1, s1.r[p1]-1)-s1.s[p1], t2 = s2.query(p2, s2.r[p2]-1)-s2.s[p2];
        ans = max(ans, t1+t2);
    }
    cout << ans << endl;

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_30115697/article/details/109486369