Submission #1085892

#TimeUsernameProblemLanguageResultExecution timeMemory
1085892kkzyrPyramid Base (IOI08_pyramid_base)C++17
100 / 100
3759 ms106204 KiB
#include <iostream> #include <algorithm> using namespace std; const int MAX_N = 1e6 + 1; const int MAX_OBSTACLES = 4e5 + 1; int n, m, b; int num_obstacles; pair<int, int> obstacle_x[MAX_OBSTACLES]; pair<int, int> obstacle_y[MAX_OBSTACLES]; int cost[MAX_OBSTACLES]; struct event{ int x, type, y_start, y_end; }; bool comp(event x, event y){ return x.x < y.x; } event events[2 * MAX_OBSTACLES]; namespace case_1{ struct node{ int left_bound, right_bound; int left_value, left_zeros; int right_value, right_zeros; int min_value, all_zeros; int lazy; }; node merge(node left, node right){ node actual_left = {left.left_bound, left.right_bound, left.left_value + left.lazy, left.left_zeros, left.right_value + left.lazy, left.right_zeros, left.min_value + left.lazy, left.all_zeros, 0}; node actual_right = {right.left_bound, right.right_bound, right.left_value + right.lazy, right.left_zeros, right.right_value + right.lazy, right.right_zeros, right.min_value + right.lazy, right.all_zeros, 0}; node x = {left.left_bound, right.right_bound, actual_left.left_value, 0, actual_right.right_value, 0, min(actual_left.min_value, actual_right.min_value), 0, 0}; if (actual_left.left_zeros == (left.right_bound - left.left_bound + 1) and actual_left.left_value == actual_right.left_value){ x.left_zeros = actual_left.left_zeros + actual_right.left_zeros; } else{ x.left_zeros = actual_left.left_zeros; } if (actual_right.right_zeros == (right.right_bound - right.left_bound + 1) and actual_left.right_value == actual_right.right_value){ x.right_zeros = actual_right.right_zeros + actual_left.right_zeros; } else{ x.right_zeros = actual_right.right_zeros; } if (actual_left.min_value == x.min_value){ x.all_zeros = max(x.all_zeros, actual_left.all_zeros); } if (actual_right.min_value == x.min_value){ x.all_zeros = max(x.all_zeros, actual_right.all_zeros); } if (actual_left.right_value == actual_right.left_value and actual_left.right_value == x.min_value){ x.all_zeros = max(x.all_zeros, actual_left.right_zeros + actual_right.left_zeros); } return x; } int size_of_tree; node tree[4 * MAX_N]; void update(int left, int right, int tree_node, int delta){ int node_left = tree[tree_node].left_bound; int node_right = tree[tree_node].right_bound; if (node_right < left or node_left > right){ return; } if (node_left >= left and node_right <= right){ tree[tree_node].lazy += delta; return; } tree[2 * tree_node].lazy += tree[tree_node].lazy; tree[2 * tree_node + 1].lazy += tree[tree_node].lazy; update(left, right, 2 * tree_node, delta); update(left, right, 2 * tree_node + 1, delta); tree[tree_node] = merge(tree[2 * tree_node], tree[2 * tree_node + 1]); } node longest_consecutive; void find_longest_consecutive(int left, int right, int tree_node){ int node_left = tree[tree_node].left_bound; int node_right = tree[tree_node].right_bound; if (node_right < left or node_left > right){ return; } if (node_left >= left and node_right <= right){ longest_consecutive = merge(longest_consecutive, tree[tree_node]); return; } tree[2 * tree_node].lazy += tree[tree_node].lazy; tree[2 * tree_node + 1].lazy += tree[tree_node].lazy; find_longest_consecutive(left, right, 2 * tree_node); find_longest_consecutive(left, right, 2 * tree_node + 1); tree[tree_node] = merge(tree[2 * tree_node], tree[2 * tree_node + 1]); } int solve(){ size_of_tree = 1; while (size_of_tree < n){ size_of_tree *= 2; } for (int i = 1;i <= size_of_tree;i++){ tree[size_of_tree + i - 1] = {i, i, 0, 1, 0, 1, 0, 1, 0}; } for (int i = size_of_tree - 1;i >= 1;i--){ tree[i] = merge(tree[2 * i], tree[2 * i + 1]); } int ans = 0; int ctr = 1; int ctr_2 = 1; int curr = 0; for (int i = 1;i <= m;i++){ while (ctr_2 <= 2 * num_obstacles and events[ctr_2].x == i){ if (events[ctr_2].type == -1){ update(events[ctr_2].y_start, events[ctr_2].y_end, 1, events[ctr_2].type); } ctr_2++; } longest_consecutive = {0, 0, 0, 0, 0, 0}; find_longest_consecutive(1, n, 1); if (longest_consecutive.all_zeros >= (curr - i + 1)){ ans = max(ans, curr - i + 1); } else{ continue; } while ((curr + 1) <= m){ curr++; while (ctr <= 2 * num_obstacles and events[ctr].x == curr){ if (events[ctr].type == 1){ update(events[ctr].y_start, events[ctr].y_end, 1, events[ctr].type); } ctr++; } longest_consecutive = {0, 0, 0, 0, 0, 0}; find_longest_consecutive(1, n, 1); if (longest_consecutive.min_value != 0 or longest_consecutive.all_zeros < (curr - i + 1)){ break; } ans = max(ans, curr - i + 1); } } cout << ans << '\n'; return 0; } }; namespace case_2{ struct node{ int left_bound, right_bound; int min; int lazy; }; node merge(node left, node right){ return {left.left_bound, right.right_bound, min(left.min + left.lazy, right.min + right.lazy), 0}; } int size_of_tree; node tree[4 * MAX_N]; void update(int left, int right, int tree_node, int delta){ int node_left = tree[tree_node].left_bound; int node_right = tree[tree_node].right_bound; if (node_right < left or node_left > right){ return; } if (node_left >= left and node_right <= right){ tree[tree_node].lazy += delta; return; } tree[2 * tree_node].lazy += tree[tree_node].lazy; tree[2 * tree_node + 1].lazy += tree[tree_node].lazy; update(left, right, 2 * tree_node, delta); update(left, right, 2 * tree_node + 1, delta); tree[tree_node] = merge(tree[2 * tree_node], tree[2 * tree_node + 1]); } int ans; void find_min_cost(int left, int right, int tree_node){ int node_left = tree[tree_node].left_bound; int node_right = tree[tree_node].right_bound; if (node_right < left or node_left > right){ return; } if (node_left >= left and node_right <= right){ ans = min(ans, tree[tree_node].min + tree[tree_node].lazy); return; } tree[2 * tree_node].lazy += tree[tree_node].lazy; tree[2 * tree_node + 1].lazy += tree[tree_node].lazy; find_min_cost(left, right, 2 * tree_node); find_min_cost(left, right, 2 * tree_node + 1); tree[tree_node] = merge(tree[2 * tree_node], tree[2 * tree_node + 1]); } int solve(){ int lo = 0; int hi = n; int answer = -1; while (lo <= hi){ int mid = (lo + hi)/2; size_of_tree = 1; while (size_of_tree < (n - mid + 1)){ size_of_tree *= 2; } for (int i = 1;i <= size_of_tree;i++){ tree[size_of_tree + i - 1] = {i, i, 0, 0}; } for (int i = size_of_tree - 1;i >= 1;i--){ tree[i] = merge(tree[2 * i], tree[2 * i + 1]); } int min_overall = 2e9 + 5; int ctr = 1; int ctr_2 = 1; while (ctr <= 2 * num_obstacles and events[ctr].x < mid){ if (events[ctr].type > 0){ update(max(1, events[ctr].y_start - mid + 1), min(n - mid + 1, events[ctr].y_end), 1, events[ctr].type); } ctr++; } for (int i = 1;i <= m - mid + 1;i++){ while (ctr_2 <= 2 * num_obstacles and events[ctr_2].x == i){ if (events[ctr_2].type < 0){ update(max(1, events[ctr_2].y_start - mid + 1), min(n - mid + 1, events[ctr_2].y_end), 1, events[ctr_2].type); } ctr_2++; } while (ctr <= 2 * num_obstacles and events[ctr].x == (i + mid - 1)){ if (events[ctr].type > 0){ update(max(1, events[ctr].y_start - mid + 1), min(n - mid + 1, events[ctr].y_end), 1, events[ctr].type); } ctr++; } ans = 2e9 + 5; find_min_cost(1, n - mid + 1, 1); min_overall = min(min_overall, ans); } if (min_overall <= b){ answer = mid; lo = mid + 1; } else{ hi = mid - 1; } } cout << answer << '\n'; return 0; } }; int main(){ cin >> m >> n >> b >> num_obstacles; for (int i = 1;i <= num_obstacles;i++){ cin >> obstacle_x[i].first >> obstacle_y[i].first >> obstacle_x[i].second >> obstacle_y[i].second >> cost[i]; if (b == 0){ events[2 * i - 1] = {obstacle_x[i].first, 1, obstacle_y[i].first, obstacle_y[i].second}; events[2 * i] = {obstacle_x[i].second + 1, -1, obstacle_y[i].first, obstacle_y[i].second}; } else{ events[2 * i - 1] = {obstacle_x[i].first, cost[i], obstacle_y[i].first, obstacle_y[i].second}; events[2 * i] = {obstacle_x[i].second + 1, -cost[i], obstacle_y[i].first, obstacle_y[i].second}; } } sort(events + 1, events + 2 * num_obstacles + 1, comp); if (b == 0){ case_1::solve(); } else{ case_2::solve(); } }
#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...
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...