Submission #790500

#TimeUsernameProblemLanguageResultExecution timeMemory
790500AlcabelAliens (IOI16_aliens)C++17
100 / 100
126 ms13000 KiB
#include <bits/stdc++.h>
#ifndef LOCAL
#include "aliens.h"
#endif
using namespace std;
 
struct Line {
    int a;
    long long b;
    Line() {}
    Line(int _a, long long _b) {
        a = _a, b = _b;
    }
    long long f(int x) {
        return a * 1ll * x + b;
    }
    ~Line() {}
};
 
int sign(long long x) {
    if (x > 0) { return 1; }
    if (x < 0) { return -1; }
    return 0;
}
 
long long intersect(const Line& A, const Line& B) {
    // x = (B.b - A.b) / (A.a - B.a)
    long long numer = B.b - A.b, denom = A.a - B.a;
    int sn = sign(numer), sd = sign(denom);
    numer *= sn, denom *= sd;
    if (sn * sd < 0) {
        return numer / denom * -1;
    }
    return (numer + denom - 1) / denom;
}
 
long long take_photos(int n, int m, int k, vector<int> rows, vector<int> cols) {
    vector<int> maxRight(m, -1);
    for (int i = 0; i < n; ++i) {
        int l = min(rows[i], cols[i]);
        int r = max(rows[i], cols[i]);
        maxRight[l] = max(maxRight[l], r + 1);
    }
    vector<pair<int, int>> segs;
    for (int l = 0; l < m; ++l) {
        if (maxRight[l] != -1 && (segs.empty() || segs.back().second < maxRight[l])) {
            segs.emplace_back(l, maxRight[l]);
        }
    }
    n = segs.size();
    /*for (const auto& [l, r] : segs) {
        cerr << l << ' ' << r << '\n';
    }*/
    k = min(k, n);
    vector<pair<long long, int>> dp(n);
    vector<Line> lines;
    vector<long long> optX;
    vector<int> cntSegs;
    auto compute = [&](long long lambda) -> int {
        lines = {};
        optX = {};
        cntSegs = {};
        dp[0] = {(segs[0].second - segs[0].first) * 1ll * (segs[0].second - segs[0].first) + lambda, 1};
        for (int i = 1, ptr = 0; i < n; ++i) {
            // cerr << "i: " << i << '\n';
            int lenInter = max(0, segs[i - 1].second - segs[i].first);
            Line l(-2 * segs[i].first, dp[i - 1].first - lenInter * 1ll * lenInter + segs[i].first * 1ll * segs[i].first);
            while (!lines.empty() && intersect(lines.back(), l) <= optX.back()) {
                optX.pop_back();
                lines.pop_back();
                cntSegs.pop_back();
            }
            if (!lines.empty()) {
                optX.emplace_back(intersect(lines.back(), l));
            } else {
                optX.emplace_back(-1);
            }
            lines.emplace_back(l);
            cntSegs.emplace_back(dp[i - 1].second);
            // cerr << "inserted!\n";
            ptr = min(ptr, (int)lines.size() - 1);
            while (ptr + 1 < (int)lines.size() && optX[ptr + 1] <= segs[i].second) {
                ++ptr;
            }
            // cerr << "found!\n";
            dp[i] = {lines[ptr].f(segs[i].second) + segs[i].second * 1ll * segs[i].second + lambda, cntSegs[ptr] + 1};
            if ((segs[i].second - segs[0].first) * 1ll * (segs[i].second - segs[0].first) + lambda < dp[i].first) {
                dp[i] = {(segs[i].second - segs[0].first) * 1ll * (segs[i].second - segs[0].first) + lambda, 1};
            }
            // cerr << "i: " << i << ", dp: " << dp[i].first << ' ' << dp[i].second << '\n';
        }
        return dp[n - 1].second;
    };
    long long left = -1, right = m * 1ll * m + 10;
    while (right - left > 1) {
        long long mid = left + (right - left) / 2;
        // cerr << "mid: " << mid << '\n';
        int res = compute(mid);
        // cerr << "res: " << res << '\n';
        if (res >= k) {
            left = mid;
        } else {
            right = mid;
        }
    }
    compute(left);
    // cerr << "right: " << right << '\n';
    // cerr << "dp: " << dp[n - 1].first << ", " << dp[n - 1].second << '\n';
    return dp[n - 1].first - k * left;
}
/*
void solve() {
    int n, m, k;
    cin >> n >> m >> k;
    vector<int> r(n), c(n);
    for (int i = 0; i < n; ++i) {
        cin >> r[i] >> c[i];
    }
    cout << take_photos(n, m, k, r, c) << '\n';
}
 
int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
 
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
        cerr << "-----------\n";
        cout << "-----------\n";
    }
#else
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
#endif
 
    return 0;
}
*/
#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...