Cod sursa(job #2692470)

Utilizator alexnekiNechifor Alexandru alexneki Data 2 ianuarie 2021 19:14:39
Problema Hotel Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.27 kb
#include <bits/stdc++.h>

using namespace std;

ifstream in("hotel.in");
ofstream out("hotel.out");

int const NMAX = 1e5;

struct NodeInfo {
    //lazy flag fields
    bool lazySet0;
    bool lazySet1;

    //actual information fields
    int maxConsZeros;
    int maxZerosAtStart;
    int maxZerosAtEnd;

    void initEmpty(int node, int left, int right) {
        lazySet0 = false;
        lazySet1 = false;
        maxConsZeros = right - left + 1;
        maxZerosAtStart = right - left + 1;
        maxZerosAtEnd = right - left + 1;
    }

    void initFull(int node, int left, int right) {
        lazySet0 = false;
        lazySet1 = false;
        maxConsZeros = 0;
        maxZerosAtStart = 0;
        maxZerosAtEnd = 0;
    }
};

NodeInfo seg[1 + 8 * NMAX]; //I added this because I was having memory issues

//COMMENT: make sure at one point you clean the mess (or push it outside the tree)
//We are assuming that through our model a node cannot be at the same time lazily set to 0 and lazily to to 1.
void cleanNode(int node, int left, int right) {
    if (seg[node].lazySet0 == true) {
        seg[node].initEmpty(node, left, right);
        seg[2 * node].lazySet0 = true;
        seg[2 * node].lazySet1 = false;
        seg[2 * node + 1].lazySet0 = true;
        seg[2 * node + 1].lazySet1 = false;
    } else if (seg[node].lazySet1 == true) {
        seg[node].initFull(node, left, right);
        seg[2 * node].lazySet0 = false;
        seg[2 * node].lazySet1 = true;
        seg[2 * node + 1].lazySet0 = false;
        seg[2 * node + 1].lazySet1 = true;
    }
}

//Here is going back up the tree after an update => we are working with real info
//The node is clean and his children are clean
//EDIT by Aarush: when debugging I found that the children weren't always clean
//so I cleaned them at the beginning
void computeNode(int node, int left, int right) {
    int mid = (left + right) / 2;

    cleanNode(node, left, right);
    cleanNode(2 * node, left, mid);
    cleanNode(2 * node + 1, mid + 1, right);

    NodeInfo &son1 = seg[2 * node];
    NodeInfo &son2 = seg[2 * node + 1];

    int size1 = mid - left + 1;
    int size2 = right - (mid + 1) + 1;

    int maxZeros = max(son1.maxConsZeros, son2.maxConsZeros);
    seg[node].maxConsZeros = max(maxZeros, son1.maxZerosAtEnd + son2.maxZerosAtStart);

    seg[node].maxZerosAtStart = son1.maxZerosAtStart;
    if (son1.maxZerosAtStart == size1) {
        seg[node].maxZerosAtStart += son2.maxZerosAtStart;
    }

    seg[node].maxZerosAtEnd = son2.maxZerosAtEnd;
    if (son2.maxZerosAtEnd == size2) {
        seg[node].maxZerosAtEnd += son1.maxZerosAtEnd;
    }
    //cout << "(" << node << " " << seg[node].maxConsZeros << ")" << "\n";
}

//PREVIOUSLY, update(int node, int left, int right, int pos, int value)
void update(int node, int left, int right, int from, int to, int val) {
    //cout << "(" << node << ", " << left << ", " << right << ") " << "[" << from << ", " << to << "] " << val << "\n";
    cleanNode(node, left, right);
    int mid = (left + right) / 2;
    if (left == from && right == to) {
        if (val == 0) {
            seg[node].lazySet0 = true;
        } else {
            seg[node].lazySet1 = true;
        }
        cleanNode(node, left, right);
    } else {
        if (from <= mid) {
            update(2 * node, left, mid, from, min(mid, to), val);
        }
        if (mid + 1 <= to) {
            update(2 * node + 1, mid + 1, right, max(mid + 1, from), to, val);
        }
        computeNode(node, left, right);
    }
}

//No point in being lazy
void build(int node, int left, int right) {
    seg[node].initEmpty(node, left, right);
    if (left != right) {
        int mid = (left + right) / 2;
        build(2 * node, left, mid);
        build(2 * node + 1, mid + 1, right);
    }
}

//in this problem updating from zero/initial state does not work, because initial zero/state has some specific modeling needed.
int main() {
    int n, p;
    in >> n >> p;
    build(1, 1, n);
    for (int i = 1; i <= p; i++) {
        int c, k1, k2;
        in >> c;
        if (c == 1) {
            in >> k1 >> k2;
            update(1, 1, n, k1, k1 + k2 - 1, 1);
        } else if (c == 2) {
            in >> k1 >> k2;
            update(1, 1, n, k1, k1 + k2 - 1, 0);
        } else {
            out << seg[1].maxConsZeros << "\n";
        }
    }
    return 0;
}