|
| 1 | +// Rozwiązanie powolne zadania 'Czekolada' z I Etapu X OI. |
| 2 | +// Autor: Paweł Putra |
| 3 | +// Złożoność czasowa: O((n + m) * log(n + m)) |
| 4 | +// Złożoność pamięciowa: O(n + m) |
| 5 | +// Punkty: 88 (upsolve) |
| 6 | +// Rozwiązanie bez obserwacji, że można zawsze łamać przez całość czekolady bez zmiany wyniku. |
| 7 | + |
| 8 | +#include <bits/stdc++.h> |
| 9 | +#define dbg(x) #x << " = " << x << " " |
| 10 | +using namespace std; |
| 11 | +constexpr int MAXN = 1005, INF = 1'000'000'000; |
| 12 | +int x[MAXN], y[MAXN]; |
| 13 | + |
| 14 | +struct MinTree { |
| 15 | + int t[4 * MAXN], n, *tab; |
| 16 | + |
| 17 | + int ql, qr; |
| 18 | + |
| 19 | + int idx_of_max(int l, int r) { |
| 20 | + ql = l, qr = r; |
| 21 | + return query(1, 1, n); |
| 22 | + } |
| 23 | + |
| 24 | + int query(int pos, int l, int r) { |
| 25 | + if (l > qr || r < ql) return 0; |
| 26 | + if (l >= ql && r <= qr) return t[pos]; |
| 27 | + int m = (l + r) / 2; |
| 28 | + int idx_l = query(pos * 2, l, m); |
| 29 | + int idx_r = query(pos * 2 + 1, m+1, r); |
| 30 | + if (tab[idx_l] > tab[idx_r]) return idx_l; |
| 31 | + return idx_r; |
| 32 | + } |
| 33 | + |
| 34 | + void build(int size, int* tab_ptr) { |
| 35 | + n = size; |
| 36 | + tab = tab_ptr; |
| 37 | + _build(1, 1, n); |
| 38 | + } |
| 39 | + |
| 40 | + void _build(int pos, int l, int r) { |
| 41 | + if (l == r) { |
| 42 | + t[pos] = l; |
| 43 | + return; |
| 44 | + } |
| 45 | + |
| 46 | + int m = (l + r) / 2; |
| 47 | + _build(pos * 2, l, m); |
| 48 | + _build(pos * 2 + 1, m + 1, r); |
| 49 | + if (tab[t[pos*2]] > tab[t[pos*2+1]]) t[pos] = t[pos*2]; |
| 50 | + else t[pos] = t[pos*2+1]; |
| 51 | + } |
| 52 | +} best_x, best_y; |
| 53 | + |
| 54 | +// Koszt podzielenia podprostokąta czekolady o współrzędnych łamań [l, r] x [d, u]. |
| 55 | +// Krawędzi jest (n-1)*m + m * (n-1) <= 2 * n*m <= 2 * 10^6. |
| 56 | +// Czyli max wynik <= 2 * 10^9. |
| 57 | +int solve(int l, int r, int d, int u) { |
| 58 | + int bx = best_x.idx_of_max(l, r); |
| 59 | + int by = best_y.idx_of_max(d, u); |
| 60 | + if (bx == 0 && by == 0) return 0; |
| 61 | + // cerr << dbg(l) << dbg(r) << dbg(d) << dbg(u) << dbg(bx) << dbg(x[bx]) << dbg(by) << dbg(y[by]) << endl; |
| 62 | + if (x[bx] > y[by]) { |
| 63 | + // cerr << "PO X" << endl; |
| 64 | + return x[bx] + solve(l, bx - 1, d, u) + solve(bx + 1, r, d, u); |
| 65 | + } else { |
| 66 | + // cerr << "PO Y" << endl; |
| 67 | + return y[by] + solve(l, r, d, by-1) + solve(l, r, by+1, u); |
| 68 | + } |
| 69 | +} |
| 70 | + |
| 71 | + |
| 72 | +int32_t main() { |
| 73 | + ios_base::sync_with_stdio(0); |
| 74 | + |
| 75 | + int m, n; |
| 76 | + |
| 77 | + cin >> m >> n; |
| 78 | + |
| 79 | + for (int i = 1; i <= m-1; i++) cin >> x[i]; |
| 80 | + for (int i = 1; i <= n-1; i++) cin >> y[i]; |
| 81 | + |
| 82 | + |
| 83 | + best_x.build(m, x); |
| 84 | + best_y.build(n, y); |
| 85 | + cout << solve(1, m-1, 1, n-1) << "\n"; |
| 86 | +} |
0 commit comments