Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Linear Programming and Greedy Approaches for Sequence Operations

Tech 3

Linear Programming Formulation

Let (\cdot) denote the dot product, with (b,c,x,y) as row vectors. For matrix (A), vectors (u,v) satisfy (u \leq v) if (\forall i, u_i \leq v_i), and similar for (\geq).

The standard linear programming (LP) problem is:

[\max c \cdot x \quad \text{s.t.} \quad \begin{cases} Ax \leq b \ x \geq 0 \end{cases}]

Its dual is:

[\min b \cdot y \quad \text{s.t.} \quad \begin{cases} A^T y \geq c \ y \geq 0 \end{cases}]

Weak duality theorem: (\max c \cdot x \leq \min b \cdot y). This holds because for any feasible (x,y), we have (y^T A x \leq y^T b = b \cdot y) and (y^T A x = (A^T y)^T x \geq c^T x = c \cdot x).

Strong duality theorem: (\max c \cdot x = \min b \cdot y), allowing transfromation of the primal problem into its dual for solution.

Application to Sequence Operations

Given a sequence, each operation is assigned an index set (I_t) for (t = 1, \dots, M). Define variable (x_t) as the number of times operation (t) is repeated, relaxed to real numbers; the optimal solution remains integer.

Constraints are split into two conditions, yielding the answer:

[\min \sum_{t=1}^M x_t \quad \text{s.t.} \quad \begin{cases} \sum_{t=1}^{M} [i \in I_t] x_t \geq a_i \ -\sum_{t=1}^{M} [i \in I_t] x_t \geq -a_i \ x_t \geq 0 \end{cases}]

Taking the dual, we have:

[\max \sum_{i=1}^n a_i (p_i - q_i) \quad \text{s.t.} \quad \begin{cases} \sum_{i=1}^{n} [i \in I_t] (p_i - q_i) \leq 1 \ p_i, q_i \geq 0 \end{cases}]

Let (y_i = p_i - q_i), which can be any real number, simplifying to:

[\max \sum_{i=1}^n a_i y_i \quad \text{s.t.} \quad \sum_{i=1}^{n} [i \in I_t] y_i \leq 1]

This matrix is totally unimodular, ensuring the LP has integer vertices and thus integer solutions. The problem reduces to assigning weights (y_i) such that for each operation, the sum of weights over its indices is at most 1.

Dynamic Programming Sollution

A classic approach similar to maximum subarray sum uses DP with three suffix sums (x,y,z) representing the maximum values after three operations, constrained by (x,y,z \leq 1). If any value drops below 0, it is "truncated" by starting a new suffix. This implies (y_i) only meaningfully takes valuees (0,1,-1); values less than -1 are truncated and not optimal since -1 is never beneficial.

Time complexity is (O(n)) with a constant factor of 24.

#include <iostream>
#include <algorithm>
#include <climits>
using namespace std;

long long readLong() {
    long long val = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    do {
        val = val * 10 + (ch - '0');
        ch = getchar();
    } while (ch >= '0' && ch <= '9');
    return val;
}

const int MAX_N = 100005;
const long long NEG_INF = LLONG_MIN / 2;
int seqLen;
long long arr[MAX_N];
long long dp[MAX_N][2][2][2];

void compute() {
    seqLen = readLong();
    for (int idx = 1; idx <= seqLen; ++idx) arr[idx] = readLong();
    for (int idx = 1; idx <= seqLen; ++idx)
        for (int a = 0; a < 2; ++a)
            for (int b = 0; b < 2; ++b)
                for (int c = 0; c < 2; ++c)
                    dp[idx][a][b][c] = NEG_INF;
    dp[0][0][0][0] = 0;
    for (int pos = 1; pos <= seqLen; ++pos) {
        for (int a = 0; a < 2; ++a) {
            for (int b = 0; b < 2; ++b) {
                for (int c = 0; c < 2; ++c) {
                    for (int delta = -1; delta <= 1; ++delta) {
                        if (a + delta > 1 || b + delta > 1) continue;
                        long long &curr = dp[pos][max(a + delta, 0)][c][max(b + delta, 0)];
                        curr = max(curr, dp[pos - 1][a][b][c] + delta * arr[pos]);
                    }
                }
            }
        }
    }
    long long best = 0;
    for (int a = 0; a < 2; ++a)
        for (int b = 0; b < 2; ++b)
            for (int c = 0; c < 2; ++c)
                best = max(best, dp[seqLen][a][b][c]);
    printf("%lld\n", best);
}

int main() {
    int testCases = readLong();
    while (testCases--) compute();
    return 0;
}

Greedy Algorithm

An alternative greedy method processes the sequence with variables tracking contributions.

#include <iostream>
#include <algorithm>
using namespace std;

long long readLong() {
    long long val = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    do {
        val = val * 10 + (ch - '0');
        ch = getchar();
    } while (ch >= '0' && ch <= '9');
    return val;
}

void greedySolve() {
    int n = readLong();
    long long contribA = 0, contribB = 0, contribC = 0;
    long long total = 0, prev = readLong();
    for (int i = 2; i <= n + 1; ++i) {
        long long curr = 0;
        if (i <= n) curr = readLong();
        long long adjust = 0;
        if (curr < contribA + contribB) {
            adjust = contribA + contribB - curr;
            if (contribA < adjust) contribB -= adjust - contribA, adjust = contribA;
            if (contribB < adjust) contribA -= adjust - contribB, adjust = contribB;
            contribA -= adjust; contribB -= adjust; curr -= adjust;
        }
        curr -= contribA + contribB;
        long long minVal = min(prev, curr);
        total += minVal; prev -= minVal; curr -= minVal; contribA += minVal;
        total += prev; contribC += prev;
        curr += adjust; total -= adjust;
        prev = curr;
        swap(contribB, contribC);
    }
    printf("%lld\n", total);
}

int main() {
    int testCases = readLong();
    while (testCases--) greedySolve();
    return 0;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.