Cod sursa(job #1112613)

Utilizator gbi250Gabriela Moldovan gbi250 Data 19 februarie 2014 21:28:11
Problema Hotel Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.58 kb
#include <cstdio>
#include <algorithm>
#define SIZE 100000
using namespace std;

int n, m, op, pos, nr, A, B;

struct tree
{
    int max_left;   // nr max de camere libere consecutive care incep pe pozitia left
    int max_right; // nr max de camere libere consecutive care se termina pe pozitia right
    int MAX;      // nr max de camere libere consecutive pe intervalul considerat
} int_tree[ 3 * SIZE];

inline void build_tree(int, int, int);
inline void update(int, int, int, int);

inline int maxim( int a, int b )
{
    if( a > b )
        return a;
    return b;
}

int main()
{
    freopen("hotel.in", "r", stdin);
    freopen("hotel.out", "w", stdout);

    scanf("%d%d", &n, &m);

    build_tree( 1, 1, n );
   // int_tree[ 1 ].max_left = int_tree[ 1 ].max_right = int_tree[ 1 ].MAX = n;

    while ( m-- )
    {
        scanf("%d", &op);

        if( op != 3)                  // insert
        {
            scanf("%d%d", &pos, &nr); // pos pozitia de inceput, nr - numarul de camere care se vor ocupa
            A = pos;
            B = pos + nr - 1;         // intervalul [A, B] => de la pos la nr se ocupa camerele
            update(1, 1, n, op);
        }

        else // query
            printf("%d\n", int_tree[ 1 ].MAX);
    }

    return 0;
}


inline void build_tree(int node, int left, int right)
{
    if( left == right )
    {
        int_tree[ node ].max_left = int_tree[ node ].max_right = int_tree[ node ].MAX = 1;
        return;
    }

    int middle = ( left + right ) / 2;

    build_tree( 2 * node, left, middle );
    build_tree( 2 * node + 1, middle + 1, right);

    int_tree[ node ].MAX = int_tree[ node ].max_left = int_tree[ node ].max_right = right - left + 1;
}

inline void fill_rooms( int node )
{
    int_tree[ node ].max_left = int_tree[ node ].max_right = int_tree[ node ].MAX = 0;
}

inline void empty_rooms( int node, int left, int right )
{
    int_tree[ node ].MAX =  int_tree[ node ].max_left = int_tree[ node ].max_right = right - left + 1;
}

inline void update(int node, int left, int right, int type)
{
    if( A <= left && right <= B)
    {
        if( type == 1 )
            fill_rooms( node );
        else
            empty_rooms( node, left, right );
     //   printf("!!!%d\n", node);
        return ;
    }

    int middle = ( right + left ) / 2;

    if( int_tree[ node ].MAX == right - left + 1)    // toate camerele din intervalul reprezentat de node sunt goale
    {
        empty_rooms( 2 * node, left, middle);       // => si cele din intervalele incluse in intervalul lui node trebuie sa fie goale
        empty_rooms( 2 * node + 1, middle + 1, right);
    }

    if( int_tree[ node ].MAX == 0)                  // camerele din intervalul reprezentat de node sunt pline
    {
        fill_rooms( 2 * node );                     // => si cele din fiii nodului node trebuie sa fie pline
        fill_rooms( 2 * node + 1);
    }

    if( A <= middle )
        update( 2 * node, left, middle, type);
    if( B > middle )
        update( 2 * node + 1, middle + 1, right, type);

    int_tree[ node ].max_left = int_tree[ 2 * node ].max_left;

    if( int_tree[ 2 * node ].max_left == middle - left + 1)
        int_tree[ node ].max_left += int_tree[ 2 * node + 1 ].max_left;

    int_tree[ node ].max_right = int_tree[ 2 * node + 1 ].max_right;

    if( int_tree[ 2 * node + 1 ].max_right == right - middle)
        int_tree[ node ].max_right += int_tree[ 2 * node ].max_right;

    int_tree[ node ].MAX = maxim( maxim(int_tree[2 * node].MAX, int_tree[ 2 * node + 1].MAX),
                                  int_tree[2 * node].max_right + int_tree[ 2 * node + 1].max_left);
}