Submission #511623

#TimeUsernameProblemLanguageResultExecution timeMemory
511623KoD3D Histogram (COCI20_histogram)C++17
110 / 110
1626 ms140636 KiB
#include <bits/stdc++.h>

using std::vector;
using std::array;
using std::pair;
using std::tuple;

using i64 = std::int64_t;

template <class F> struct RecLambda : private F {
    explicit RecLambda(F&& f) : F(std::forward<F>(f)) {}
    template <class... Args> decltype(auto) operator()(Args&&... args) const {
        return F::operator()(*this, std::forward<Args>(args)...);
    }
};

void setmax(i64& x, const i64 y) {
    if (x < y) {
        x = y;
    }
}

struct Line {
    i64 a, b;
    i64 eval(const i64 x) const { 
        return a * x + b; 
    }
};

i64 rem_euclid(i64 a, const i64 b) {
    a %= b;
    return a < 0 ? a + b : a;
}

i64 floor_div(const i64 a, const i64 b) {
    return (a - rem_euclid(a, b)) / b;
}

i64 ceil_div(const i64 a, const i64 b) {
    return floor_div(a + b - 1, b);
}

struct CHT {
    std::deque<Line> line;
    CHT() : line() {}
    i64 change(const Line& l, const Line& m) {
        return ceil_div(m.b - l.b, l.a - m.a);
    }
    void add(const Line& l) {
        int n = line.size();
        if (n > 0 and line[n - 1].a == l.a) {
            return;
        }
        while (n >= 2) {
            if (change(line[n - 2], line[n - 1]) < change(line[n - 1], l)) {
                break;
            }
            line.pop_back();
            n -= 1;
        }
        line.push_back(l);
    }
    i64 max(const i64 x) {
        int n = line.size();
        if (n == 0) {
            return 0;
        }
        while (n >= 2 and line[0].eval(x) <= line[1].eval(x)) {
            line.pop_front();
            n -= 1;
        }
        return line[0].eval(x);
    }
};

struct Segtree {
    int size;
    vector<CHT> data;
    Segtree(const int n) : size(n), data(2 * n) {}
    void add(int k, const Line& l) {
        k += size;
        while (k > 0) {
            data[k].add(l);
            k >>= 1;
        }
    }
    i64 max(int l, int r, const i64 x) {
        l += size, r += size;
        i64 ret = 0;
        while (l < r) {
            if (l & 1) {
                setmax(ret, data[l].max(x));
                l += 1;
            }
            if (r & 1) {
                r -= 1;
                setmax(ret, data[r].max(x));
            }
            l >>= 1, r >>= 1;
        }
        return ret;
    }
};

i64 solve(const int n, const vector<int>& x1, const vector<int>& y1, const int m, const vector<int>& x2, const vector<int>& y2) {
    Segtree seg(m);
    for (int i = m - 1; i >= 0; --i) {
        seg.add(i, Line{y2[i], (i64)y2[i] * (i + 1)});
    }
    int j = 0, k = 0;
    i64 ret = 0;
    for (int i = 0; i < n; ++i) {
        while (j < m and x1[i] <= x2[j]) {
            j += 1;
        }
        while (k < j and y1[i] < y2[k]) {
            k += 1;
        }
        if (k != 0) {
            setmax(ret, (i64)x1[i] * y1[i] * (i + 1 + k));
        }
        if (k != j) {
            setmax(ret, (i64)x1[i] * seg.max(k, j, i + 1));
        }
    }
    return ret;
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int N;
    std::cin >> N;
    vector<int> A(N), B(N);
    i64 ans = 0;
    for (int i = 0; i < N; ++i) {
        std::cin >> A[i] >> B[i];
        setmax(ans, (i64)A[i] * B[i]);
    }
    RecLambda([&](auto&& dfs, const int left, const int right) -> void {
        if (right - left <= 1) return;
        const int mid = (left + right) / 2;
        dfs(left, mid);
        dfs(mid, right);
        const int lsize = mid - left, rsize = right - mid;
        vector<int> x1(lsize), y1(lsize), x2(rsize), y2(rsize);
        for (int i = mid - 1, a = 1000000, b = 1000000; i >= left; --i) {
            a = std::min(a, A[i]);
            b = std::min(b, B[i]);
            setmax(ans, (i64)a * b * (mid - i));
            x1[mid - i - 1] = a, y1[mid - i - 1] = b;
        }
        for (int i = mid, a = 1000000, b = 1000000; i < right; ++i) {
            a = std::min(a, A[i]);
            b = std::min(b, B[i]);
            setmax(ans, (i64)a * b * (i - mid + 1));
            x2[i - mid] = a, y2[i - mid] = b;
        }
        setmax(ans, solve(lsize, x1, y1, rsize, x2, y2));
        setmax(ans, solve(rsize, x2, y2, lsize, x1, y1));
    })(0, N);
    std::cout << ans << '\n';
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...