Submission #1329402

#TimeUsernameProblemLanguageResultExecution timeMemory
1329402jochisFeast (NOI19_feast)C++20
4 / 100
30 ms9148 KiB
#include <bits/stdc++.h>
using namespace std;

struct Node {
    long long val;   // valor del elemento
    int idx;         // índice en el array original (inicio del bloque)
    int l, r;        // índices de bloques vecinos (-1 si no existe)
    
    // Para ordenar por valor ascendente en el priority queue
    bool operator<(const Node& other) const {
        return val > other.val;  // Invertido para min-heap
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int N, K;
    if (!(cin >> N >> K)) return 0;
    
    vector<long long> A(N);
    for (int i = 0; i < N; i++) cin >> A[i];
    
    // ===== FASE 1: Preprocesar =====
    // Combinar elementos del mismo signo
    vector<long long> B;  // Array preprocesado
    vector<int> startIdx; // Índice de inicio de cada bloque en A original
    
    for (int i = 0; i < N; i++) {
        if (B.empty() || (A[i] >= 0 && B.back() < 0) || (A[i] < 0 && B.back() >= 0)) {
            B.push_back(A[i]);
            startIdx.push_back(i);
        } else {
            B.back() += A[i];
        }
    }
    
    // Eliminar negativos de los extremos
    while (!B.empty() && B.front() < 0) {
        B.erase(B.begin());
        startIdx.erase(startIdx.begin());
    }
    while (!B.empty() && B.back() < 0) {
        B.pop_back();
        startIdx.pop_back();
    }
    
    int M = B.size();
    if (M == 0) {
        cout << 0 << "\n";
        return 0;
    }
    
    // ===== FASE 2: Verificar si hay más positivos que K =====
    // Contar positivos
    int posCount = 0;
    for (int i = 0; i < M; i++) {
        if (B[i] > 0) posCount++;
    }
    
    // Si hay <= K positivos, sumar todos
    if (posCount <= K) {
        long long ans = 0;
        for (int i = 0; i < M; i++) {
            if (B[i] > 0) ans += B[i];
        }
        cout << ans << "\n";
        return 0;
    }
    
    // ===== FASE 3: Eliminar K menores positivos =====
    // Usar priority queue para elementos positivos
    priority_queue<Node> pq;
    vector<bool> removed(M, false);
    
    // Insertar todos los positivos en el pq
    for (int i = 0; i < M; i++) {
        if (B[i] > 0) {
            pq.push({B[i], startIdx[i], i - 1, i + 1});
        }
    }
    
    // Eliminar K veces el menor positivo
    for (int iter = 0; iter < K; iter++) {
        if (pq.empty()) break;
        
        Node cur = pq.top();
        pq.pop();
        
        // Verificar si este nodo ya fue invalidado
        if (removed[cur.idx]) continue;
        
        // Marcar como procesado
        removed[cur.idx] = true;
        
        // Combinar con vecinos
        int L = cur.l;
        int R = cur.r;
        
        // Encontrar vecinos válidos (no eliminados)
        while (L >= 0 && removed[L]) L--;
        while (R < M && removed[R]) R++;
        
        if (L >= 0 && R < M) {
            // Ambos vecinos existen: combinar los tres
            // El menor valor absorbe a los otros dos
            long long vals[3] = {B[cur.idx], B[L], B[R]};
            
            // Encontrar el índice del menor
            int minIdx = 0;
            if (vals[1] < vals[minIdx]) minIdx = 1;
            if (vals[2] < vals[minIdx]) minIdx = 2;
            
            if (minIdx == 0) {
                // El actual absorbe a ambos
                B[cur.idx] = B[L] + B[cur.idx] + B[R];
                removed[L] = removed[R] = true;
                
                // Actualizar vecinos del nuevo nodo
                int newL = L - 1;
                while (newL >= 0 && removed[newL]) newL--;
                int newR = R + 1;
                while (newR < M && removed[newR]) newR++;
                
                // Insertar de nuevo si es positivo
                if (B[cur.idx] > 0) {
                    pq.push({B[cur.idx], startIdx[cur.idx], newL, newR});
                }
            } else if (minIdx == 1) {
                // Izquierdo absorbe
                B[L] = B[L] + B[cur.idx] + B[R];
                removed[cur.idx] = removed[R] = true;
                
                int newL = L - 1;
                while (newL >= 0 && removed[newL]) newL--;
                int newR = R + 1;
                while (newR < M && removed[newR]) newR++;
                
                if (B[L] > 0) {
                    pq.push({B[L], startIdx[L], newL, newR});
                }
            } else {
                // Derecho absorbe
                B[R] = B[L] + B[cur.idx] + B[R];
                removed[cur.idx] = removed[L] = true;
                
                int newL = L - 1;
                while (newL >= 0 && removed[newL]) newL--;
                int newR = R + 1;
                while (newR < M && removed[newR]) newR++;
                
                if (B[R] > 0) {
                    pq.push({B[R], startIdx[R], newL, newR});
                }
            }
        } else if (L >= 0) {
            // Solo vecino izquierdo
            B[L] += B[cur.idx];
            removed[cur.idx] = true;
            
            int newL = L - 1;
            while (newL >= 0 && removed[newL]) newL--;
            
            if (B[L] > 0) {
                pq.push({B[L], startIdx[L], newL, L + 1});
            }
        } else if (R < M) {
            // Solo vecino derecho
            B[R] += B[cur.idx];
            removed[cur.idx] = true;
            
            int newR = R + 1;
            while (newR < M && removed[newR]) newR++;
            
            if (B[R] > 0) {
                pq.push({B[R], startIdx[R], R - 1, newR});
            }
        }
        // Si no hay vecinos, simplemente se elimina (queda en 0)
    }
    
    // ===== FASE 4: Calcular respuesta =====
    long long ans = 0;
    for (int i = 0; i < M; i++) {
        if (!removed[i] && B[i] > 0) {
            ans += B[i];
        }
    }
    
    cout << ans << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...