Submission #1022975

#TimeUsernameProblemLanguageResultExecution timeMemory
1022975shiomusubi496Wiring (IOI17_wiring)C++17
100 / 100
110 ms20808 KiB
#include "wiring.h" #include <bits/stdc++.h> #define rep(i, n) for (int i = 0; i < (int)(n); ++i) #define rep2(i, a, b) for (int i = (int)(a); i < (int)(b); ++i) #define rrep(i, n) for (int i = (int)(n) - 1; i >= 0; --i) #define rrep2(i, a, b) for (int i = (int)(b) - 1; i >= (int)(a); --i) #define all(v) begin(v), end(v) using namespace std; template<class T, class U> bool chmin(T& a, const U& b) { return a > b ? a = b, true : false; } template<class T, class U> bool chmax(T& a, const U& b) { return a < b ? a = b, true : false; } using ll = long long; constexpr ll inf = 1e18; class LiChaoTree { struct Line { ll a, b; Line(ll a, ll b) : a(a), b(b) {} ll get(ll x) const { return a * x + b; } }; int n; vector<Line> seg; void add_line(Line line, int k, int l, int r) { int m = (l + r) / 2; ll lx = seg[k].get(l), rx = seg[k].get(r - 1), mx = seg[k].get(m); ll ly = line.get(l), ry = line.get(r - 1), my = line.get(m); if (lx <= ly && rx <= ry) return; if (lx >= ly && rx >= ry) { seg[k] = line; return; } if (mx > my) { swap(seg[k], line); swap(mx, my); swap(lx, ly); swap(rx, ry); } if (lx > ly) { add_line(line, 2 * k, l, m); } else if (rx > ry) { add_line(line, 2 * k + 1, m, r); } } void add_segment(Line line, int a, int b, int k, int l, int r) { if (b <= l || r <= a) return; if (a <= l && r <= b) { add_line(line, k, l, r); return; } int m = (l + r) / 2; add_segment(line, a, b, 2 * k, l, m); add_segment(line, a, b, 2 * k + 1, m, r); } public: LiChaoTree(int n_) { n = 1; while (n < n_) n <<= 1; seg.assign(2 * n, Line(0, inf)); } void add_segment(int l, int r, ll a, ll b) { add_segment(Line(a, b), l, r, 1, 0, n); } ll get(int x) { int k = x + n; ll res = inf; while (k > 0) { chmin(res, seg[k].get(x)); k >>= 1; } return res; } }; long long min_total_length(std::vector<int> r, std::vector<int> b) { int N = r.size(), M = b.size(); vector<pair<ll, int>> A(N + M); rep (i, N) A[i] = {r[i], 0}; rep (i, M) A[N + i] = {b[i], 1}; sort(all(A)); vector<int> nxt(N + M + 1); nxt[N + M] = N + M; nxt[N + M - 1] = N + M; rrep (i, N + M - 1) { if (A[i].second == A[i + 1].second) nxt[i] = nxt[i + 1]; else nxt[i] = i + 1; } vector<ll> cum1(N + M), cum2(N + M); rep (i, N + M - 1) cum1[i + 1] = cum1[i] + (A[i + 1].first - A[i].first) * i; LiChaoTree lct(N + M + 1); vector<ll> dp(N + M + 1, inf); dp[0] = 0; rep (i, N + M) { int m = nxt[i]; int r = nxt[m]; if (m != r) { ll tmp1 = (dp[i] + cum1[m] * 2 - cum1[i] + (A[m].first - A[i].first) * (-i + 1)); ll tmp2 = (dp[i] + cum1[m - 1] * 2 - cum1[i] + (A[m - 1].first - A[i].first) * (-i + 1)); int mm = clamp(2 * m - i, m, r); lct.add_segment(m, mm, -A[m].first, tmp1); lct.add_segment(mm, r, -A[m - 1].first, tmp2); } if (i != 0 && A[i].second != A[i - 1].second) { ll tmp = dp[i] + cum1[i - 1]; lct.add_segment(i, m, -A[i - 1].first, tmp); } dp[i + 1] = lct.get(i) + A[i].first * i - cum1[i]; } return dp[N + M]; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...