Submission #1293675

#TimeUsernameProblemLanguageResultExecution timeMemory
1293675whyamihereIdeal city (IOI12_city)C++20
100 / 100
42 ms11136 KiB
#include <bits/stdc++.h> using namespace std; // Assumes points are sorted by X then Y // Always makes cuts horizontally vector<pair<uint32_t, vector<size_t>>> to_tree(vector<pair<int32_t, int32_t>> points) { vector<pair<uint32_t, vector<size_t>>> tree; vector<tuple<int32_t, int32_t, size_t>> ranges; // Group points by X coordinate size_t i = 0; while (i < points.size()) { int32_t current_x = points[i].first; vector<pair<int32_t, int32_t>> x_chunk; while (i < points.size() && points[i].first == current_x) { x_chunk.push_back(points[i]); i++; } vector<tuple<int32_t, int32_t, size_t>> new_ranges; size_t closest_range = 0; // Group x_chunk by consecutive Y coordinates size_t j = 0; while (j < x_chunk.size()) { int32_t min_y = x_chunk[j].second; int32_t max_y = min_y; while (j + 1 < x_chunk.size() && x_chunk[j + 1].second == x_chunk[j].second + 1) { j++; max_y = x_chunk[j].second; } size_t node_idx = tree.size(); uint32_t height = (uint32_t)abs(max_y - min_y) + 1; vector<size_t> children; while (closest_range < ranges.size()) { int32_t closest_min_x = get<0>(ranges[closest_range]); int32_t closest_max_x = get<1>(ranges[closest_range]); size_t closest_node = get<2>(ranges[closest_range]); if (closest_min_x <= max_y && closest_max_x >= min_y) { children.push_back(closest_node); tree[closest_node].second.push_back(node_idx); } if (closest_max_x >= max_y) break; closest_range++; } tree.push_back({height, children}); new_ranges.push_back({min_y, max_y, node_idx}); j++; } ranges = new_ranges; } return tree; } uint32_t calculate_result_for_tree(uint32_t total_points, vector<pair<uint32_t, vector<size_t>>>& tree, uint32_t modulo) { vector<size_t> to_evaluate; uint32_t sum = 0; // Find all leaf nodes (nodes with only 1 connection) for (size_t idx = 0; idx < tree.size(); idx++) { if (tree[idx].second.size() == 1) { to_evaluate.push_back(idx); } } while (!to_evaluate.empty()) { size_t node_idx = to_evaluate.back(); to_evaluate.pop_back(); auto node = tree[node_idx]; sum = (sum + (uint64_t)node.first * (total_points - node.first)) % modulo; // Remove this node from its neighbors for (size_t neighbour : node.second) { // Remove node_idx from neighbour's children auto& neighbour_children = tree[neighbour].second; neighbour_children.erase( remove(neighbour_children.begin(), neighbour_children.end(), node_idx), neighbour_children.end() ); tree[neighbour].first += node.first; if (tree[neighbour].second.size() == 1) { to_evaluate.push_back(neighbour); } } } return sum; } uint32_t solve(vector<pair<int32_t, int32_t>> points, uint32_t modulo) { uint32_t total_points = points.size(); // Horizontal sort vector<pair<int32_t, int32_t>> horizontal_sort = points; sort(horizontal_sort.begin(), horizontal_sort.end()); vector<pair<uint32_t, vector<size_t>>> horizontal_tree = to_tree(horizontal_sort); uint32_t horizontal_value = calculate_result_for_tree(total_points, horizontal_tree, modulo); // Vertical sort vector<pair<int32_t, int32_t>> vertical_sort; for (auto& p : points) { vertical_sort.push_back({p.second, p.first}); } sort(vertical_sort.begin(), vertical_sort.end()); vector<pair<uint32_t, vector<size_t>>> vertical_tree = to_tree(vertical_sort); uint32_t vertical_value = calculate_result_for_tree(total_points, vertical_tree, modulo); return (horizontal_value + vertical_value) % modulo; } int DistanceSum(int N, int *X, int *Y) { vector<pair<int32_t, int32_t>> points; for (int i = 0; i < N; i++) { points.push_back({X[i], Y[i]}); } return solve(points, 1000000000); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...