# | Time | Username | Problem | Language | Result | Execution time | Memory |
---|---|---|---|---|---|---|---|
731602 | jasen_penchev | Aliens (IOI16_aliens) | C++14 | 0 ms | 0 KiB |
This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
/// Conveh Hull Trick Optimization
#include <algorithm>
#include <iostream>
#include <utility>
#include <vector>
#include <deque>
#define endl '\n'
using namespace std;
const long long INF = (long long)(1e18);
struct line
{
long long a, b;
long long calc(long long x)
{
return (a * x + b);
}
long double intersect(line l)
{
return (long double)(l.b - b) / (a - l.a);
}
};
long long take_photos(int n, int m, int k, vector<int> row, vector<int> col)
{
vector< pair<int, int> > temp;
for (int i = 0; i < n; ++ i)
{
temp.push_back({max(row[i], col[i]), min(row[i], col[i])});
}
sort(temp.begin(), temp.end());
vector< pair<int, int> > interv;
interv.push_back({-1, -1});
for (auto [r, l] : temp)
{
while (interv.size() and interv.back().first >= l) interv.pop_back();
interv.push_back({l, r});
}
n = interv.size() - 1;
vector< vector<long long> > dp(n + 1, vector<long long>(k + 1, INF));
for (int i = 1; i <= n; ++ i)
{
dp[i][1] = 1ll * (interv[i].second - interv[1].first + 1) * (interv[i].second - interv[1].first + 1);
}
long long ret = dp[n][1];
for (int j = 2; j <= min(n, k); ++ j)
{
deque<line> dq;
dq.push_back({-2ll * interv[j].first, dp[j - 1][j - 1] + 1ll * interv[j].first * interv[j].first - 1ll * max(0, interv[j - 1].second - interv[j].first + 1) * max(0, interv[j - 1].second - interv[j].first + 1)});
for (int i = j; i <= n; ++ i)
{
while (dq.size() >= 2 and dq[0].calc(interv[i].second + 1) >= dq[1].calc(interv[i].second + 1)) dq.pop_front();
dp[i][j] = dq[0].calc(interv[i].second + 1) + 1ll * (interv[i].second + 1) * (interv[i].second + 1);
line curr = {-2ll * interv[i + 1].first, dp[i][j - 1] + 1ll * interv[i + 1].first * interv[i + 1].first - 1ll * max(0, interv[i].second - interv[i + 1].first + 1) * max(0, interv[i].second - interv[i + 1].first + 1)};
while (dq.size() >= 2 and curr.intersect(dq.back()) <= dq.back().intersect(dq[dq.size() - 2])) dq.pop_back();
dq.push_back(curr);
}
ret = min(ret, dp[n][j]);
}
return ret;
}
int main()
{
ios :: sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
int n, m, k;
cin >> n >> m >> k;
vector<int> row, col;
for (int i = 1; i <= n; ++ i)
{
int r, c;
cin >> r >> c;
row.push_back(r);
col.push_back(c);
}
cout << take_photos(n, m, k, row, col) << endl;
return 0;
}