제출 #1208130

#제출 시각아이디문제언어결과실행 시간메모리
1208130gatapdevK개의 묶음 (IZhO14_blocks)C++20
0 / 100
1 ms328 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = LLONG_MAX / 4;

int n, K;
vector<ll> a;
vector<vector<ll>> stMax;
vector<int> log2v;

// Precompute sparse table for RMQ max
void buildSparse() {
    log2v.assign(n + 2, 0);
    for (int i = 2; i <= n; i++) log2v[i] = log2v[i / 2] + 1;
    int maxLog = log2v[n];
    stMax.assign(maxLog + 1, vector<ll>(n + 2, 0));
    for (int i = 1; i <= n; i++) stMax[0][i] = a[i];
    for (int k = 1; k <= maxLog; k++) {
        for (int i = 1; i + (1 << k) - 1 <= n; i++) {
            stMax[k][i] = max(stMax[k - 1][i], stMax[k - 1][i + (1 << (k - 1))]);
        }
    }
}

// Query max in a[l..r]
ll queryMax(int l, int r) {
    if (l > r) return 0;
    int len = r - l + 1;
    int k = log2v[len];
    return max(stMax[k][l], stMax[k][r - (1 << k) + 1]);
}

vector<ll> dp_prev, dp_cur;

// Divide-and-conquer optimization to fill dp_cur[L..R]
void compute(int k, int L, int R, int optL, int optR) {
    if (L > R) return;
    int mid = (L + R) >> 1;
    ll bestVal = INF;
    int bestPos = optL;
    int start = max(optL, k - 1);
    int end = min(optR, mid - 1);
    for (int j = start; j <= end; j++) {
        ll val = dp_prev[j] + queryMax(j + 1, mid);
        if (val < bestVal) {
            bestVal = val;
            bestPos = j;
        }
    }
    dp_cur[mid] = bestVal;
    compute(k, L, mid - 1, optL, bestPos);
    compute(k, mid + 1, R, bestPos, optR);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> K;
    a.resize(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];

    buildSparse();
    dp_prev.assign(n + 1, INF);
    dp_cur.assign(n + 1, INF);
    dp_prev[0] = 0;

    // base k=1: prefix max
    for (int i = 1; i <= n; i++) dp_prev[i] = max(dp_prev[i - 1], a[i]);

    // DP for k=2..K using divide-and-conquer optimization
    for (int k = 2; k <= K; k++) {
        fill(dp_cur.begin(), dp_cur.end(), INF);
        compute(k, k, n, 0, n - 1);
        dp_prev = dp_cur;
    }

    cout << dp_prev[n] << '\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...