Cod sursa(job #3260263)

Utilizator BledeaAlexBledea Alexandru BledeaAlex Data 1 decembrie 2024 12:24:52
Problema Hotel Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.14 kb
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N_MAX = 1e5 + 1, INF = INT_MAX;
int N, M;

void SetInput(string name)
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    freopen((name + ".in").c_str(), "r", stdin);
    freopen((name + ".out").c_str(), "w", stdout);
}

struct LazySegmentTree
{
    struct Node
    {
        int maxi; // the length of the longest subarray of 0
        int leftMaxi, rightMaxi;
        int len;

        void SetAllValues(int value)
        {
            maxi = leftMaxi = rightMaxi = value;
        }

        bool flagged; // means that this node's children are not updated
    };

    Node A[4 * N_MAX];
    int bg, ed, value; // local variables for Update and Query

    inline int Maxi(int a, int b)
    {
        return a > b ? a : b;
    }

    Node MaxiR(Node& a, Node& b) // Maxi with both Nodes as references
    {
        Node temp;
        temp.leftMaxi = a.leftMaxi;
        if(a.leftMaxi == a.len)
            temp.leftMaxi = b.leftMaxi + a.len;
        temp.rightMaxi = b.rightMaxi;
        if(b.rightMaxi == b.len)
            temp.rightMaxi = a.rightMaxi + b.len;
        temp.maxi = max({temp.leftMaxi, temp.rightMaxi, a.rightMaxi + b.leftMaxi, a.maxi, b.maxi});
        temp.len = a.len + b.len;
        temp.flagged = false;

        return temp;
    }

    Node Maxi(Node& a, Node b) // Maxi with one Node as references
    {
        Node temp;
        temp.leftMaxi = a.leftMaxi;
        if(a.leftMaxi == a.len)
            temp.leftMaxi = b.leftMaxi + a.len;
        temp.rightMaxi = b.rightMaxi;
        if(b.rightMaxi == b.len)
            temp.rightMaxi = a.rightMaxi + b.len;
        temp.maxi = max({temp.leftMaxi, temp.rightMaxi, a.rightMaxi + b.leftMaxi, a.maxi, b.maxi});
        temp.len = a.len + b.len;
        temp.flagged = false;

        return temp;
    }

    void Build(int node, int L, int R)
    {
        if(L == R)
        {
            // cin >> A[node].value;
            /// We set all base nodes to 0, so the max is the node's length
            A[node].SetAllValues(1);
            A[node].len = 1;
            A[node].flagged = false;
            return;
        }

        int m = (L + R) >> 1;
        Build(node << 1, L, m);
        Build((node << 1) + 1, m + 1, R);

        A[node] = MaxiR(A[node << 1], A[(node << 1) + 1]);
        A[node].len = R - L + 1;
    }

    void Update(int bg, int ed, int value) // Value can be 0 or 1
    {
        this->bg = bg;
        this->ed = ed;
        this->value = value;

        _Update(1, 1, N);
    }

    void _Update(int node, int L, int R)
    {
        if(bg <= L && R <= ed)
        {
            if(value == 0)
                A[node].SetAllValues(R - L + 1);
            else
                A[node].SetAllValues(0);

            A[node].flagged = true;
            return;
        }

        if(A[node].flagged)
        {
            if(A[node].maxi == 0)
            {
                A[node << 1].SetAllValues(0);
                A[(node << 1) + 1].SetAllValues(0);
            }else
            {
                A[node << 1].SetAllValues(A[node << 1].len);
                A[(node << 1) + 1].SetAllValues(A[(node << 1) + 1].len);
            }

            A[node << 1].flagged = A[(node << 1) + 1].flagged = true;

            A[node].flagged = false;
        }

        int m = (L + R) >> 1;

        if(bg <= m)
            _Update(node << 1, L, m);
        if(m < ed)
            _Update((node << 1) + 1, m + 1, R);

        A[node] = MaxiR(A[node << 1], A[(node << 1) + 1]);
    }

    int Query(int bg, int ed)
    {
        this->bg = bg;
        this->ed = ed;

        return Query(1, 1, N);
    }

    int Query(int node, int L, int R)
    {
        if(bg <= L && R <= ed)
            return A[node].maxi;

        if(A[node].flagged)
        {
            if(A[node].maxi == 0)
            {
                A[node << 1].SetAllValues(0);
                A[(node << 1) + 1].SetAllValues(0);
            }else
            {
                A[node << 1].SetAllValues(A[node << 1].len);
                A[(node << 1) + 1].SetAllValues(A[(node << 1) + 1].len);
            }

            A[node << 1].flagged = A[(node << 1) + 1].flagged = true;

            A[node].flagged = false;
        }

        int m = (L + R) >> 1;

        int temp = -INF;
        if(bg <= m)
            temp = Maxi(temp, Query(node << 1, L, m));
        if(m < ed)
            temp = Maxi(temp, Query((node << 1) + 1, m + 1, R));

        return temp;
    }

} tree;

int main()
{
    SetInput("hotel");

    cin >> N >> M;
    tree.Build(1, 1, N);
    int t, a, b;
    while(M--)
    {
        cin >> t;
        switch(t)
        {
            case 1:
                cin >> a >> b;
                tree.Update(a, a + b - 1, 1);
                break;
            case 2:
                cin >> a >> b;
                tree.Update(a, a + b - 1, 0);
                break;
            case 3:
                cout << tree.A[1].maxi << '\n';
        }
    }

    return 0;
}