Cod sursa(job #3134692)

Utilizator DenisaCrCranganu Denisa Mariana DenisaCr Data 30 mai 2023 13:20:42
Problema Hotel Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.18 kb

#include <iostream>
#include <fstream>
#include <algorithm>

using namespace std;

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

struct node // structura unui nod din arbore
{
	int st, dr, total;
};

const int N = 100005;

int n, q; // n = numarul de camere, q = numarul de operatii
node arb[4 * N]; // arborele
int hotel[4 * N];

int max(int a, int b, int c) // functie care returneaza maximul dintre 3 numere
{
	return max(max(a, b), c);
}

void updateNode(int ti, int tl, int tr) // functia face update la nodul cu indexul ti
{
	arb[ti].total = max(arb[ti * 2].total, arb[ti * 2 + 1].total, arb[ti * 2].dr + arb[ti * 2 + 1].st); // actualizez valoarea totala

	int mid = (tl + tr) / 2; // mijlocul intervalului

	arb[ti].st = arb[ti * 2].st; // actualizez valoarea stanga
	if (arb[ti].st == mid - tl + 1)  // daca valoarea stanga este egala cu lungimea intervalului
	{
		arb[ti].st += arb[ti * 2 + 1].st; // actualizez valoarea stanga
	}

	arb[ti].dr = arb[ti * 2 + 1].dr; // actualizez valoarea dreapta
	if (arb[ti].dr == tr - mid) // daca valoarea dreapta este egala cu lungimea intervalului
	{
		arb[ti].dr += arb[ti * 2].dr; // actualizez valoarea dreapta
	}
}

void build(int tl = 1, int tr = n, int ti = 1) // functia construieste arborele
{
	if (tl == tr) // daca am ajuns la o frunza
	{
		arb[ti].dr = arb[ti].st = arb[ti].total = 1; // initializam valorile
		return;
	}

	int mid = (tl + tr) / 2; // mijlocul intervalului
	build(tl, mid, ti * 2); // construim subarborele stang
	build(mid + 1, tr, ti * 2 + 1); // construim subarborele drept
	updateNode(ti, tl, tr); // actualizam nodul
}

void update(int qt, int ql, int qr, int tl = 1, int tr = n, int ti = 1)
{
	// 1 = ocupa camere
	// 2 = elibereaza camere

	int lungime = tr - tl + 1; // lungimea intervalului
	if (hotel[ti]) // daca nodul este marcat
	{
		if (hotel[ti] == 1) // daca nodul este marcat cu 1
		{
			arb[ti].dr = arb[ti].st = arb[ti].total = 0; // dreapta, stanga si totalul devin 0
		}
		else
		{
			arb[ti].dr = arb[ti].st = arb[ti].total = lungime;  // dreapta, stanga si totalul devin lungimea intervalului
		}

		if (tl < tr) // daca nu am ajuns la o frunza
		{
			hotel[ti * 2] = hotel[ti * 2 + 1] = hotel[ti];
		}

		hotel[ti] = 0;
	}

	// not included
	if (tr < ql || qr < tl) // daca intervalul nu este inclus in intervalul dat
	{
		return;
	}

	// fully included
	if (ql <= tl && tr <= qr) // daca intervalul este inclus in intervalul dat
	{
		if (qt == 1)
		{
			arb[ti].dr = arb[ti].st = arb[ti].total = 0;
		}
		else
		{
			arb[ti].dr = arb[ti].st = arb[ti].total = lungime;
		}

		if (tl < tr)
		{
			hotel[ti * 2] = hotel[ti * 2 + 1] = qt;
		}
		return;
	}

	// partial included
	int mid = (tl + tr) / 2;
	update(qt, ql, qr, tl, mid, ti * 2);
	update(qt, ql, qr, mid + 1, tr, ti * 2 + 1);
	updateNode(ti, tl, tr);
}

int main()
{
	f >> n >> q;

	build();

	while (q--) // cat timp mai am operatii de facut
	{
		int c;
		f >> c;
		if (c == 3) // daca cererea este de tipul 3
		{
			g << arb[1].total << '\n';
		}
		else
		{
			int l, nr;
			f >> l >> nr;
			int r = l + nr - 1;
			update(c, l, r);
		}
	}
}