Submission #160113

#TimeUsernameProblemLanguageResultExecution timeMemory
160113rama_pangWall (IOI14_wall)C++14
100 / 100
1644 ms162284 KiB
#include "wall.h"
#include <bits/stdc++.h>
using namespace std;

/*  Keep a lower bound and upper bound of heights in each node of
    segment tree. To propagate, just get the values of the parent
    node and update its lower bound and upper bound. For query, just
    traverse through the segment tree for each node (point query).
*/

struct segtree {
    struct Node {
        int val_min, val_max;
        int lazy_min; // val_min and val_max should not be lower than this
        int lazy_max; // val_min and val_max should not be higher than this

        Node(): val_min(0), val_max(0), lazy_min(-1), lazy_max(-1) {}

    };

    vector<Node> tree;

    inline void lazydown(int n) {
        if (tree[n].lazy_min != -1) {
            tree[n * 2].val_min = max(tree[n * 2].val_min, tree[n].lazy_min);
            tree[n * 2].val_max = max(tree[n * 2].val_max, tree[n].lazy_min);
            
            tree[n * 2 + 1].val_min = max(tree[n * 2 + 1].val_min, tree[n].lazy_min);
            tree[n * 2 + 1].val_max = max(tree[n * 2 + 1].val_max, tree[n].lazy_min);
        }

        if (tree[n].lazy_max != -1) {
            tree[n * 2].val_min = min(tree[n * 2].val_min, tree[n].lazy_max);
            tree[n * 2].val_max = min(tree[n * 2].val_max, tree[n].lazy_max);

            tree[n * 2 + 1].val_min = min(tree[n * 2 + 1].val_min, tree[n].lazy_max);
            tree[n * 2 + 1].val_max = min(tree[n * 2 + 1].val_max, tree[n].lazy_max);
        }

        tree[n * 2].lazy_min = tree[n * 2].val_min;
        tree[n * 2].lazy_max = tree[n * 2].val_max;

        tree[n * 2 + 1].lazy_min = tree[n * 2 + 1].val_min;
        tree[n * 2 + 1].lazy_max = tree[n * 2 + 1].val_max;
        
        tree[n].lazy_min = tree[n].lazy_max = -1;
    }

    void init(int n) {
        tree.resize(4 * n + 5);
    }

    void update(int n, int tl, int tr, int le, int ri, int val, int type) {
        if (tl > tr || tl > ri || tr < le) return;
        if (le <= tl && tr <= ri) {
            if (type == 1) { // add
                tree[n].val_max = max(tree[n].val_max, val);
                tree[n].val_min = max(tree[n].val_min, val);
                tree[n].lazy_min = tree[n].val_min;
                tree[n].lazy_max = tree[n].val_max;
            }

            if (type == 2) { // remove
                tree[n].val_max = min(tree[n].val_max, val);
                tree[n].val_min = min(tree[n].val_min, val);
                tree[n].lazy_max = tree[n].val_max;
                tree[n].lazy_min = tree[n].val_min;
            }
            
            return;
        }

        int mid = (tl + tr) / 2;
        lazydown(n);
        update(n * 2, tl, mid, le, ri, val, type);
        update(n * 2 + 1, mid + 1, tr, le, ri, val, type);
        tree[n].val_min = min(tree[n * 2].val_min, tree[n * 2 + 1].val_min);
        tree[n].val_max = max(tree[n * 2].val_max, tree[n * 2 + 1].val_max);
    }

    int query(int n, int tl, int tr, int p) {
        if (tl == tr) return tree[n].val_min;

        int mid = (tl + tr) / 2;
        lazydown(n);
        if (p <= mid) 
            return query(n * 2, tl, mid, p);
        else 
            return query(n * 2 + 1, mid + 1, tr, p);
    }

} solver;

void buildWall(int n, int k, int op[], int left[], int right[], int height[], int finalHeight[]){
    solver.init(n);
    for (int i = 0; i < k; i++) solver.update(1, 0, n - 1, left[i], right[i], height[i], op[i]);
    for (int i = 0; i < n; i++) finalHeight[i] = solver.query(1, 0, n - 1, i);
    return;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...