Cod sursa(job #2007940)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 4 august 2017 16:59:13
Problema Hotel Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.45 kb
#include <iostream>
#include <fstream>

#define ll long long
#define pb push_back
using namespace std;
ifstream in("hotel.in");
ofstream out("hotel.out");

const int NMax = 1e5 + 5;
const int arbMax = 262144 + 5;

int N,M;
short lazy[arbMax];
// lazy[i] = 1 daca este necesar un update de ocupare pe nodul cu indexul node
// lazy[i] = -1 daca este necesar un update de golire pe nodul cu indexul node
// lazy[i] = 0 daca nu este necesar un update

struct elem {
    int free = 0,st = 0,dr = 0;
}arb[arbMax];
// arb[i].free = numarul maxim de camere consecutive libere din intervalul curent;
// arb[i].st = numarul de camere consecutive libere pornind de la stanga intervalului;
// arb[i].st = numarul de camere consecutive libere pornind de la dreapta intervalului;

void update(int,int,int,int,int,bool);

int main() {
    in>>N>>M;
    update(1,1,N,1,N,true);
    // se face un update care elibereaza toate camerele;

    while (M--) {
        int tip,a,b;
        in>>tip;
        if (tip == 3) {
            out<<arb[1].free<<'\n';
        }
        else {
            in>>a>>b;
            b = a+b-1;

            if (tip == 1) {
                update(1,1,N,a,b,false);
            }
            else {
                update(1,1,N,a,b,true);
            }
        }
    }

    in.close();out.close();
    return 0;
}

// node - indexul nodului curent
// [st;dr] - intervalul retinut de nodul curent
// [a;b] - intervalul pe care se face update
// golire = true daca se elibereaza camere
// golire = false daca se ocupa camere
void update(int node,int st,int dr,int a,int b,bool golire) {
    int fs = node<<1, ss = fs+1;

    // se face lazy update-ul ramas pe acest nod
    if (lazy[node] != 0) {
        if (lazy[node] == 1) {
            arb[node].free = arb[node].st = arb[node].dr = 0;
        }
        else if (lazy[node] == -1) {
            arb[node].free = arb[node].st = arb[node].dr = (dr-st+1);
        }

        if (st != dr) {
            lazy[fs] = lazy[node];
            lazy[ss] = lazy[node];
        }
        lazy[node] = 0;
    }

    // daca intervalele nu au elemente comune, se iese din functie;
    // se poate ajunge in acest caz deoarece
    // mai jos se apeleaza ambele update-uri intotdeauna;
    // acest lucru este necesar pentru a face lazy update-urile necesare
    // pe fii inainte de a modifica valoarea din acest nod;
    if (b < st || dr < a) {
        return;
    }

    if (a <= st && dr <= b) {
        if (golire) {
            arb[node].free = arb[node].st = arb[node].dr = (dr-st+1);
            if (st != dr) {
                lazy[fs] = -1;
                lazy[ss] = -1;
            }
        }
        else {
            arb[node].free = arb[node].st = arb[node].dr = 0;
            if (st != dr) {
                lazy[fs] = 1;
                lazy[ss] = 1;
            }
        }
        return;
    }

    int mij = (st+dr)>>1;
    update(fs,st,mij,a,b,golire);
    update(ss,mij+1,dr,a,b,golire);

    // daca fiul stang are toate camerele libere, atunci cele din stanga se pot continua cu arb[ss].st;
    arb[node].st = arb[fs].st + ((arb[fs].free == mij-st+1) ? arb[ss].st : 0);
    // daca fiul drept are toate camerele libere, atunci cele din dreapta se pot continua cu arb[fs].dr;
    arb[node].dr = arb[ss].dr + ((arb[ss].free == dr-(mij+1)+1) ? arb[fs].dr : 0);
    arb[node].free = max(arb[fs].dr + arb[ss].st,max(arb[fs].free,arb[ss].free));
}