【题 解】 CF1359D 【Otra tarea más】

El jefe de línea de escaneo es realmente fuerte ...

Déjame hablar sobre mi extraño enfoque.

De acuerdo con el significado de la pregunta, siempre que primero seleccione un intervalo, el valor máximo debe eliminarse, luego podemos considerar enumerar el valor máximo eliminado.

Entonces, considerando cada número como el rango al que puede afectar el valor máximo, es obvio que la pila monótona se puede usar para encontrar el primero a la izquierda y a la derecha que sea más grande que él.

KI iiestoy en[l, r] [l, r][ l ,r ] es el valor máximo, entonces tenemos que partir de esta posición y encontrar un segmento y el subsegmento más grande de izquierda a derecha respectivamente.

Considere el lado derecho primero, y el lado izquierdo es el mismo. Prefijamos y sumamos la secuencia original, luego tenemos que encontrar [i, r] [i, r][ yo ,El valor máximo de la suma del prefijo en r ] . Entonces usamos la tabla st para preprocesar y consultar el valor máximo del intervalo.

Para la conveniencia del código, se abren dos matrices para manejar las situaciones izquierda y derecha respectivamente.

#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;
}

Supongo que te gusta

Origin blog.csdn.net/qq_30115697/article/details/109486369
Recomendado
Clasificación