[CSP-S 2019] divided D2T2

Description

Portal

Solution

Algorithm 1 12pts

Index algorithm just messing around.

Algorithm 2 36pts

\(O(n^3)\)dp。

Set \ (f_ {i, j} \) represents the position \ (J \) at the end, a decision point \ (J \) the minimum value of.

Transfer is obvious:

Order \ (S_I = \ SUM \ limits_ ^ {J} = {I}. 1 a_j \) , i.e., the prefix and.

then

\[f_{i,j}=f_{j,k}+(s_i-s_j)^2$,其中 $s_i-s_j \ge s_j-s_k\]

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

typedef long long ll;

inline ll ty() {
    char ch = getchar(); ll x = 0, f = 1;
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

const int _ = 5000 + 10;
int n, type;
ll A[_], sum[_], f[_][_], ans;

inline ll _2(ll x) { return x * x; }

int main() {
    n = ty(), type = ty();
    for (int i = 1; i <= n; ++i) {
        A[i] = ty();
        sum[i] = sum[i - 1] + A[i];
        // cout << sum[i] << endl;
    }
    memset(f, 0x3f, sizeof(f));
    ans = f[0][0];
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= i; ++j) {
            if (j == 1) f[i][j] = _2(sum[i]);
            else
                for (int k = 1; k < j; ++k)
                    if (sum[i] - sum[j - 1] >= sum[j - 1] - sum[k - 1])
                        f[i][j] = min(f[i][j], f[j - 1][k] + _2(sum[i] - sum[j - 1]));
        }
    }
    
    for (int i = 1; i <= n; ++i) ans = min(ans, f[n][i]);
    printf("%lld\n", ans);
    return 0;
}

Algorithm 3 64pts

\ (O (^ n-2) \) DP. The konjac because I was too, so do not write. The idea is probably

"May be fixed \ (J \) , found in a mobile \ (I \) process, \ (K \) are moved to meet a monotonic, then we maintain a \ (f_ {j, k} \) of the minimum value on it. "

Algorithm 4 84 / 100pts

It is said that can be found by playing table, To prove the link , when in the last paragraph to meet the solvability of the case and the most hours, the best answer.

Thus may be provided \ (G_i \) represents the position \ (I \) , the minimum value of the position of a decision point in the case of solvability, i.e.,

\[g_i = \max \limits_{j=0}^{i-1}j, s.t. s_i-s_j \ge s_j-s_{g_j}\]

Slightly shifted entries can be obtained

\[s_i \ge 2s_j-s_{g_j}\]

Obviously this is monotonous, so you can maintain with a monotonous queue.

Code

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

inline int ty() {
    char ch = getchar(); int x = 0, f = 1;
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}

typedef long long ll;
const int _ = 5e5 + 10;
int n, type, a[_], q[_], g[_];
ll sum[_], ans;

inline ll calc(int j) { return 2ll * sum[j] - sum[g[j]]; }
inline ll _2(const ll &x) { return x * x; }

int main() {
#ifndef ONLINE_JUDGE
    freopen("divide.in", "r", stdin);
    freopen("divide.out", "w", stdout);
#endif
    n = ty(), type = ty();
    for (int i = 1; i <= n; ++i) a[i] = ty(), sum[i] = sum[i - 1] + a[i];
    int h = 1, t = 1;
    for (int i = 1; i <= n; ++i) {
        while (h < t && calc(q[h + 1]) <= sum[i]) ++h;
        g[i] = q[h];
        while (h < t && calc(q[t]) >= calc(i)) --t;
        q[++t] = i;
    }
    int now = n;
    while (now) {
        ans = ans + _2(sum[now] - sum[g[now]]);
        now = g[now];
    }
    printf("%lld\n", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/newbielyx/p/12031507.html