제출 #1022975

#제출 시각아이디문제언어결과실행 시간메모리
1022975shiomusubi496전선 연결 (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...