Submission #275971

#TimeUsernameProblemLanguageResultExecution timeMemory
275971hamerinAliens (IOI16_aliens)C++17
41 / 100
2107 ms390520 KiB
#include "aliens.h"

#include <bits/stdc++.h>

#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")

using namespace std;

using i64 = long long;
using d64 = long double;
using pi = pair<int, int>;
using pli = pair<i64, i64>;
using ti = tuple<int, int, int>;
using tli = tuple<i64, i64, i64>;

#define iterall(cont) cont.begin(), cont.end()
#define prec(n) setprecision(n) << fixed

const i64 inf = numeric_limits<i64>::max() / 3;

class Line {
   public:
    i64 a, b;

    Line() { a = 0, b = inf; }

    Line(i64 _a, i64 _b) { a = _a, b = _b; }

    inline i64 get(i64 x) { return a * x + b; }
};

class Node {
   public:
    i64 s, e;
    Line v;
    Node *l, *r;

    Node() {
        s = e = 0;
        v = Line();
        l = r = nullptr;
    }

    Node(i64 _s, i64 _e) {
        s = _s, e = _e;
        v = Line();
        l = r = nullptr;
    }

    Node(i64 _s, i64 _e, i64 _a, i64 _b) {
        s = _s, e = _e;
        v = Line(_a, _b);
        l = r = nullptr;
    }
};

namespace LiChao {
    Node* init(i64 s, i64 e) { return new Node(s, e); }

    void update(Node* here, const Line d) {
        i64 s = here->s, e = here->e;
        i64 m = (s + e) / 2;

        auto lo = here->v, hi = d;
        if (lo.get(s) > hi.get(s)) swap(lo, hi);

        if (lo.get(e) < hi.get(e)) {
            here->v = lo;
            return;
        }

        if (lo.get(m) < hi.get(m)) {
            here->v = lo;
            if (!here->r) here->r = new Node(m + 1, e);
            update(here->r, hi);
        } else {
            here->v = hi;
            if (!here->l) here->l = new Node(s, m);
            update(here->l, lo);
        }
    }

    i64 query(Node* here, const i64 x) {
        if (!here) return inf;

        i64 s = here->s, e = here->e;
        i64 m = (s + e) / 2;

        return min(here->v.get(x), x <= m ? query(here->l, x) : query(here->r, x));
    }
};  // namespace LiChao

inline i64 sq(const i64& x) {
    return x * x;
}

inline i64 sq(i64&& x) {
    return x * x;
}

i64 take_photos(int n, int m, int k, std::vector<int> r, std::vector<int> c) {
    vector<pi> cords(n);
    for (int i = 0; i < n; i++) cords[i] = {min(r[i], c[i]), max(r[i], c[i])};
    sort(iterall(cords), [](pi l, pi r) {
        return l.first == r.first ? l.second > r.second : l.first < r.first;
    });
    cords.erase(unique(iterall(cords)), cords.end());

    vector<i64> xc(1), yc(1);
    for (auto [x, y] : cords) {
        if (yc.size() == 1 || yc.back() < y) {
            xc.emplace_back(x);
            yc.emplace_back(y);
        }
    }
    for (auto& y : yc) ++y;

    const int N = xc.size() - 1;
    // for (int i = 1; i <= N; i++) cout << xc[i] << " " << yc[i] << endl;
    vector<Node*> roots(k + 1);
    for (int i = 0; i <= k; i++) roots[i] = LiChao::init(-1000001, 1000001);
    roots[0]->v.b = 0;

    vector<vector<i64>> D(N + 1, vector<i64>(k + 1, inf));
    for (int i = 1; i <= N; i++) {
        for (int j = k; j >= 1; j--) {
            if (j == 1) {
                D[i][j] = sq(yc[i] - xc[1]);
            } else {
                D[i][j] = sq(yc[i]) + LiChao::query(roots[j - 1], yc[i]);
            }

            // cout << i << " " << j << " " << D[i][j] << endl;
            if (i != N && D[i][j] < inf) {
                LiChao::update(roots[j],
                               Line(-2 * xc[i + 1],
                                    D[i][j] - sq(max(0LL, yc[i] - xc[i + 1])) + sq(xc[i + 1])));
            }
        }
    }

    i64 ret = inf;
    for (int j = 1; j <= k; j++) ret = min(ret, D[N][j]);

    return ret;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...