답안 #1085892

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1085892 2024-09-09T01:56:33 Z kkzyr Pyramid Base (IOI08_pyramid_base) C++17
100 / 100
3759 ms 106204 KB
#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();
    }
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 344 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 348 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 2 ms 348 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 8 ms 1628 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 72 ms 9752 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 775 ms 74324 KB Output is correct
2 Correct 770 ms 74376 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 790 ms 74320 KB Output is correct
2 Correct 778 ms 74580 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 13 ms 856 KB Output is correct
2 Correct 51 ms 1372 KB Output is correct
3 Correct 48 ms 1116 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 303 ms 5724 KB Output is correct
2 Correct 416 ms 5768 KB Output is correct
3 Correct 395 ms 5716 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1391 ms 18260 KB Output is correct
2 Correct 188 ms 1872 KB Output is correct
3 Correct 322 ms 34540 KB Output is correct
4 Correct 3279 ms 34944 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 2021 ms 35268 KB Output is correct
2 Correct 3450 ms 35292 KB Output is correct
3 Correct 1060 ms 18768 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1156 ms 19268 KB Output is correct
2 Correct 3539 ms 35688 KB Output is correct
3 Correct 3759 ms 35664 KB Output is correct
4 Correct 3588 ms 35632 KB Output is correct
5 Correct 3572 ms 35676 KB Output is correct
6 Correct 457 ms 19316 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1424 ms 90284 KB Output is correct
2 Correct 1018 ms 24916 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1562 ms 98128 KB Output is correct
2 Correct 1668 ms 97620 KB Output is correct
3 Correct 787 ms 97256 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1781 ms 106204 KB Output is correct
2 Correct 2035 ms 105672 KB Output is correct
3 Correct 2033 ms 105568 KB Output is correct
4 Correct 1875 ms 105296 KB Output is correct
5 Correct 1584 ms 105676 KB Output is correct