1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
| #include <bits/stdc++.h> using namespace std; #define ri register #define id(x) (lower_bound(b + 1, b + L + 1, x) - b) #define rid(x) b[x] #define lson(x) node[x].l #define rson(x) node[x].r #define node_id(x) node[x].node_id #define sum(x) node[x].sum typedef long long ll; typedef pair<int, ll> pii;
const int INF = 0x3f3f3f3f; const int MAXN = 50005; const int MAXM = 50005; int cnt_node = 0; namespace MCMF { struct Edge { int u, v, val, cos, next; } e[MAXM * 2]; int n, m, t = 1, Head[MAXN], v[MAXN], S, T; deque<int> q; ll d[MAXN], Delta; inline void AddEdge(int x, int y, int v, int c) { e[++t] = (Edge){ x, y, v, c, Head[x] }, Head[x] = t; e[++t] = (Edge){ y, x, 0, -c, Head[y] }, Head[y] = t; } inline bool Relabel(void) { memset(d, 0x3f, sizeof d); memset(v, 0, sizeof v); d[T] = 0, v[T] = 1, q.push_front(T); while (!q.empty()) { int x = q.front(); q.pop_front(), v[x] = 0; if (q.size() > 1 && d[q.front()] > d[q.back()]) swap(q.front(), q.back()); for (int i = Head[x], y; i; i = e[i].next) if (e[i ^ 1].val && d[y = e[i].v] > d[x] + e[i ^ 1].cos) { d[y] = d[x] + e[i ^ 1].cos; if (v[y]) continue; v[y] = true, q.push_back(y); if (q.size() > 1 && d[q.front()] > d[q.back()]) swap(q.front(), q.back()); } } return d[S] != d[0]; } inline int Dinic(int x, int flow) { if (!flow || x == T) return flow; int residue = flow; v[x] = true; for (int i = Head[x], y; i; i = e[i].next) if (e[i].val && !v[y = e[i].v] && !e[i].cos) { int k = Dinic(y, min(e[i].val, residue)); e[i].val -= k, e[i ^ 1].val += k; if ((residue -= k) == 0) break; } return flow - residue; } inline pii PrimalDual(void) { int Maxflow = 0; ll Mincost = 0; while (Relabel()) { for (int i = 2; i <= t; i++) e[i].cos += d[e[i].v] - d[e[i].u]; Delta += d[S]; int Flow = 0; while (memset(v, 0x00, sizeof v), (Flow = Dinic(S, INF))) Maxflow += Flow, Mincost += 1ll * Flow * Delta; } return pii(Maxflow, Mincost); } } int n, w; pair<ll, int> a[MAXN]; ll b[MAXN], c[MAXN]; int L;
int root0[MAXN], root1[MAXN]; int pos0[MAXN], pos1[MAXN];
struct Node { int l, r, node_id, sum; } node[MAXN * 22]; int cnt = 0;
void AddEdge(int u, int l, int r, int p, bool t) { int mid = (l + r) >> 1; int llen = mid - l + 1, rlen = r - mid; int lsum = sum(lson(u)), rsum = sum(rson(u)); if (lson(u)) MCMF ::AddEdge(node_id(u), node_id(lson(u)), lsum, llen == 1 ? (t == 0 ? -c[l] : c[l]) : 0); if (rson(u)) MCMF ::AddEdge(node_id(u), node_id(rson(u)), rsum, rlen == 1 ? (t == 0 ? -c[r] : c[r]) : 0); }
void insert(int v, int& u, int l, int r, int p, bool t) { u = ++cnt; if (l == r) { sum(u) = 1; node_id(u) = l; return; } node_id(u) = ++cnt_node; int mid = (l + r) >> 1; if (p <= mid) insert(lson(v), lson(u), l, mid, p, t), rson(u) = rson(v); else insert(rson(v), rson(u), mid + 1, r, p, t), lson(u) = lson(v); sum(u) = sum(lson(u)) + sum(rson(u)); AddEdge(u, l, r, p, t); }
void query(int u, int l, int r, int ql, int qr, int cur, int num, bool t) { if (u == 0) return; if (ql <= l && r <= qr) { MCMF ::AddEdge(cur, node_id(u), sum(u), l == r ? abs(c[num] - c[l]) : (t == 0 ? c[num] : -c[num])); return; } int mid = (l + r) >> 1; if (ql <= mid) query(lson(u), l, mid, ql, qr, cur, num, t); if (mid < r) query(rson(u), mid + 1, r, ql, qr, cur, num, t); }
int main() { scanf("%d%d", &n, &w); for (int i = 1; i <= n; ++i) scanf("%lld", &a[i].first), b[i] = c[i] = a[i].first, a[i].second = i; sort(b + 1, b + n + 1); L = unique(b + 1, b + n + 1) - b - 1; sort(a + 1, a + n + 1); cnt_node = n; root0[0] = ++cnt, node_id(root0[0]) = ++cnt_node; for (int i = 1; i <= n; ++i) { pos0[id(a[i].first)] = i; insert(root0[i - 1], root0[i], 1, n, a[i].second, 0); } reverse(a + 1, a + n + 1); root1[0] = ++cnt, node_id(root1[0]) = ++cnt_node; for (int i = 1; i <= n; ++i) { pos1[id(a[i].first)] = i; insert(root1[i - 1], root1[i], 1, n, a[i].second, 1); } MCMF ::S = ++cnt_node, MCMF ::T = ++cnt_node; for (int i = 1; i < n; ++i) { query(root0[pos0[id(c[i])]], 1, n, i + 1, n, ++cnt_node, i, 0); query(root1[pos1[id(c[i])]], 1, n, i + 1, n, cnt_node, i, 1); MCMF ::AddEdge(MCMF ::S, cnt_node, 1, 0); MCMF ::AddEdge(i, MCMF ::T, 1, 0); MCMF ::AddEdge(MCMF ::S, i, 1, w); } MCMF ::AddEdge(MCMF ::S, ++cnt_node, 1, 0); MCMF ::AddEdge(n, MCMF ::T, 1, 0); MCMF ::AddEdge(MCMF ::S, n, 1, w); pii ans = MCMF ::PrimalDual(); printf("%lld\n", ans.second); return 0; }
|