Appearance
Submitted 2026-09-08 — all 1 sample case(s) passed.
cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
// USACO Landscaping (Gold/Platinum) — min cost to turn A into B.
// Operations: buy a unit (X), remove a unit (Y), or move a unit between
// beds i,j at cost Z*|i-j|.
//
// Idea: "unroll" each bed into |A_i - B_i| unit points on the number line
// (a surplus point for A_i>B_i, a deficit point for A_i<B_i), then match
// source->target points. Edit-distance style: matching a source at s with a
// target at t costs min(Z*|s-t|, X+Y) (a distance that isn't worth moving is a
// buy+remove), unmatched sources cost Y, unmatched targets cost X. In an
// optimal matching, edges do not cross; grouping by "level" makes each level an
// alternating source/target sequence, and each level is solved independently.
const int MAX_TOT = 100000 * 10; // N_max * K_max
static vector<int> rows[2 * MAX_TOT + 5]; // rows[lvl] : positions, alternating source/target
static int rtype[2 * MAX_TOT + 5]; // +1 source, -1 target (for the unmatched odd element)
static LL res1[2 * MAX_TOT + 5], res2[2 * MAX_TOT + 5];
int N;
LL X, Y, Z;
// dp over an alternating sequence v[0..M-1] (+/-), all matched.
// results[j] (j odd) = min cost to fully match v[0..j].
// Pairing is non-crossing; for a matched pair we either use a direct
// consecutive edge ("short") or a "long" edge capped at X+Y that swallows a
// balanced inner region.
static void dp(const vector<int>& v, LL* results) {
const LL M = (LL)v.size();
LL i = -2, prefcost_i = 0, prefcost_j = 0, prevLong = LLONG_MAX / 4;
for (LL j = 1; j < M; j += 2) {
if (j > 1) {
LL cost = Z * abs(v[j - 2] - v[j - 1]); // edge (j-2, j-1)
prefcost_j += cost;
prevLong += cost;
}
// find the cheapest "long edge" (i, j): its inner region is matched
// consecutively, the prefix before i is optimally matched.
while (i + 2 < j && X + Y <= Z * abs(v[j] - v[i + 2])) {
i += 2;
if (i > 0) prefcost_i += Z * abs(v[i] - v[i - 1]);
prevLong = min(prevLong,
X + Y + (prefcost_j - prefcost_i) + (i > 0 ? results[i - 1] : 0));
}
// short edge (j-1, j) plus optimally matched prefix
results[j] = min(prevLong,
Z * abs(v[j] - v[j - 1]) + (j > 1 ? results[j - 2] : 0));
}
}
// Solve one level. ecost = cost of the single unmatched element (Y if it's a
// surplus source, X if it's a deficit target).
static LL solveLevel(vector<int>& v, LL ecost) {
const LL M = (LL)v.size();
if (M == 0) return 0;
if (M == 1) return ecost;
dp(v, res1);
reverse(v.begin(), v.end());
dp(v, res2);
reverse(res2, res2 + M);
reverse(v.begin(), v.end()); // restore for any caller
if (M % 2 == 0) return res1[M - 1]; // all matched
// odd: one element left out; split into balanced prefix + that element +
// balanced suffix.
LL best = ecost + min(res1[M - 2], res2[1]);
for (LL i = 2; i <= M - 3; i += 2)
best = min(best, res1[i - 1] + ecost + res2[i + 1]);
return best;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
if (!(cin >> N >> X >> Y >> Z)) return 0;
memset(rtype, 0, sizeof(rtype));
for (int lvl = 0; lvl < 2 * MAX_TOT + 5; lvl++) rows[lvl].clear();
int lastDir = 0, level = MAX_TOT;
for (int i = 1; i <= N; i++) {
int a, b;
cin >> a >> b;
int dir = (max(a, b) == a) ? +1 : -1; // +1 surplus, -1 deficit
int m = max(a, b) - min(a, b);
while (m-- > 0) {
if (lastDir == dir) level += dir; // same sign climbs a level
if (rtype[level] == 0) rtype[level] = dir;
rows[level].push_back(i);
lastDir = dir;
}
}
LL total = 0;
for (int lvl = 0; lvl < 2 * MAX_TOT + 5; lvl++)
total += solveLevel(rows[lvl], rtype[lvl] > 0 ? Y : X);
cout << total << '\n';
return 0;
}