Submission #599581

#TimeUsernameProblemLanguageResultExecution timeMemory
599581jophyyjhAliens (IOI16_aliens)C++14
25 / 100
204 ms2272 KiB
/** * I don't feel like fully solving this, so maybe i'll just score some partials. * * [S1] Too trivial * [S2] Each point lies on the main diagonal. Clearly, no two squares should have * common squares, which means the points are partitioned into contiguous * segments. O(n^2 * k) dp kills it. * [S3] Maybe we can somehow sort the points based on their columns, then apply [S2]? * Yep, pretty much analagous to [S2]. The key here is that if (2,5), (3,5), * the square that covers (2,5) must cover (3,5). * Well, i really shouldn't have written "Too trivial" in [S1]. The following * observation is: if two segments (a1,b1) (a2,b2) satisfy a1 <= a2 and * b1 >= b2, the former's square completely contains the latter, so we shall * remove the latter. This means when we sort the points based on their b * values, a values are strictly increasing, ENSURING that intersection of area * is calculated correctly. So in fact, [S3] = [S1] + [S2]! * * Time Complexity: O(n^2 * k) * Implementation 1.5 (first 3 tasks) */ #include <bits/stdc++.h> #include "aliens.h" typedef long long ll; const int N_MAX = 500; const int INF = 0x3f3f3f3f; inline ll sqr(int k) { return ll(k) * ll(k); } ll cover[N_MAX + 1][N_MAX + 1]; struct point_t { int i, j; }; inline bool operator==(const point_t& p1, const point_t& p2) { return p1.i == p2.i && p1.j == p2.j; } ll take_photos(int n, int m, int max_sqr, std::vector<int> row, std::vector<int> col) { std::vector<point_t> values(n); for (int k = 0; k < n; k++) values[k].i = std::min(row[k], col[k]), values[k].j = std::max(row[k], col[k]); std::sort(values.begin(), values.end(), [](const point_t& p1, const point_t& p2) { return p1.j < p2.j || (p1.j == p2.j && p1.i > p2.i); }); // The most important part I missed in the first few submissions: std::vector<bool> skipped(n, false); for (int k = n - 1, suffix_min = INF; k >= 0; k--) { if (values[k].i >= suffix_min) skipped[k] = true; suffix_min = std::min(suffix_min, values[k].i); } int front = 0; // an algo. working like std::unique() for (int k = 0; k < n; k++) { if (skipped[k]) continue; values[front++] = values[k]; } n = front; // std::cerr << "debug: " << n << std::endl; // for (int i = 0; i < n; i++) // std::cerr << values[i].i << ' ' << values[i].j << std::endl; for (int k = 0; k <= n; k++) { for (int s = 0; s <= max_sqr; s++) cover[k][s] = INF; } cover[0][0] = 0; for (int k = 0; k < n; k++) { for (int s = 1; s <= max_sqr; s++) { for (int m = k, left = INF; m >= 0; m--) { // [m,k] int prev = (m > 0 ? values[m - 1].j : -1); left = std::min(left, values[m].i); cover[k + 1][s] = std::min( cover[k + 1][s], cover[m][s - 1] + sqr(values[k].j - left + 1) - sqr(std::max(prev - left + 1, 0)) ); } } } ll area = INF; for (int s = 1; s <= max_sqr; s++) area = std::min(area, cover[n][s]); return area; }
#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...