Cod sursa(job #936956)

Utilizator AndreiRSStatescu Andrei Rares AndreiRS Data 9 aprilie 2013 11:02:24
Problema Hotel Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.45 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <math.h>
#include <stdlib.h>
using namespace std;

const int dim = 100005;
int N, M, nodinterior, nodmargin1, nodmargin2, tip;
int pozs, pozd, pozsupdate, pozdupdate, valupdate, pozq, lg, index;
int H[dim], PH[dim * 2], PS[dim * 2], PD[dim * 2], AI[dim * 4];

void destroy (int nh);
void shrink_right (int nh);
void shrink_left (int nh);
void split (int nh);
int create ();
int xpand_right (int nh);
int expand_left (int nh);
int merge (int nh1, int nh2);
void modifica_interval (int nh);

bool cmpheap (int n1, int n2)
{
	return PD[H[n1]] - PS[H[n1]] > PD[H[n2]] - PS[H[n2]];
}

void upheap (int n)
{
	int t = n >> 1;
	while (t != 0 && cmpheap (n, t))
	{
		swap (H[n], H[t]);
		swap (PH[n], PH[t]);
		
		n = t;
		t = n >> 1;		
	}
}

void downheap (int n)
{
	int f = n << 1;
	if (f+1 <= H[0] && cmpheap (f+1, f)) f++;
	while (f <= H[0] && cmpheap (f, n))
	{
		swap (H[n], H[f]);
		swap (PH[n], PH[f]);
		
		n = f;
		f = n << 1;
		if (f+1 <= H[0] && cmpheap (f+1, f)) f++;
	}
}

void initializari ()
{
	index = 1;
	for (int i = 1; i < dim; i++)
	{
		PS[i] = PD[i] = -1;
		AI[i] = 1;
	}
	H[H[0] = 1] = 1;
	PH[1] = 1;
	PS[1] = 1;
	PD[1] = N;
}

void update (int nod, int st, int dr)
{
	if (nod > 1 && AI[nod >> 1] != -1)
		AI[nod] = AI[nod >> 1];
	if (pozdupdate < st || dr < pozsupdate)
		return;
	
	if (pozsupdate <= st && dr <= pozdupdate)
	{
		AI[nod] = valupdate;
		return;
	}
	
	int m = (st + dr) >> 1;
	int f1 = nod << 1;
	int f2 = f1 + 1;
	
	update (f1, st, m);
	update (f2, m + 1, dr);
	
	if (AI[f1] == AI[f2])
		AI[nod] = AI[f1];
	else
		AI[nod] = -1;
}

int query (int nod, int st, int dr)
{
	if (nod > 1 && AI[nod >> 1] != -1)
		AI[nod] = AI[nod >> 1];
	if (pozq < st || dr < pozq)
		return 0;
	
	if (pozq == st && pozq == dr)
	{
		return nod;
	}
	
	int m = (st + dr) >> 1, ok = 0;
	int f1 = nod << 1;
	int f2 = f1 + 1;
	
	ok = ok | query (f1, st, m);
	ok = ok | query (f2, m + 1, dr);
	
	if (AI[f1] == AI[f2])
		AI[nod] = AI[f1];
	else
		AI[nod] = -1;
	return ok;
}

void citeste ()
{
	scanf ("%d%d", &pozs, &lg);
	pozd = pozs + lg - 1;
	
	pozq = pozs - 1;
	nodmargin1 = pozs == 1 ? 0 : query (1, 1, N);
	
	pozq = pozd + 1;
	nodmargin2 = pozd == N ? 0 : query (1, 1, N);
	
	if (tip == 1)
	{
		pozq = pozs;
		nodinterior = query (1, 1, N);	
	}
}

void destroy (int nh)
{
	//elimina elementul nh din heap
	int n = H[H[0]--];
	PH[n] = PH[nh];
	H[PH[n]] = n;
	upheap (PH[n]);
	downheap (PH[n]);
}

void shrink_right (int nh)
{
	//elimina o bucata din stanga elemntului nh din heap aflat la dreapta intervalului citit
	PS[nh] = pozd + 1;
	upheap (PH[nh]);
	downheap (PH[nh]);
	
	modifica_interval (nh);
}

void shrink_left (int nh)
{
	//elimina o bucata din dreapta elementului nh din heap aflat la stanga intervalului citit
	PD[nh] = pozs - 1;
	upheap (PH[nh]);
	downheap (PH[nh]);
	
	modifica_interval (nh);
}

void split (int nh)
{
	//nodul nh din heap se va imparti in nodul nh care se termina la capatul stanga
	//al intervalului citit si nodul nh2 care incepe la capatul din dreapta intervalului citit
	int nh2 = ++index;
	H[++H[0]] = nh2;
	PH[nh2] = H[0];
	PS[nh2] = PS[nh];
	PD[nh2] = PD[nh];
	
	shrink_left (nh);
	shrink_right (nh2);
}

int create ()
{
	//creeaza elementul din heap nh pe intervalul citit 
	int nh = ++index;
	
	H[++H[0]] = nh;
	PH[nh] = H[0];
	PS[nh] = pozs;
	PD[nh] = pozd;
	
	upheap (PH[nh]);
	downheap (PH[nh]);

	modifica_interval (nh);
	return nh;
}

int xpand_right (int nh)
{
	//expandez catre stanga elementul nh din heap aflat in dreapta intervalului curent
	PS[nh] = pozs;
	upheap (PH[nh]);
	downheap (PH[nh]);

	modifica_interval (nh);
	return nh;
}

int xpand_left (int nh)
{
	//expandez catre dreapta elementul nh din heap situat la stanga intervalului curent
	PD[nh] = pozd;
	upheap (PH[nh]);
	downheap (PH[nh]);

	modifica_interval (nh);
	return nh;
}

int merge (int nh1, int nh2)
{
	//unesc elementele din heap nh1 si nh2
	//reuniunea lor va fi nh1 iar pe nh2 il distrug
	PD[nh1] = PD[nh2];
	destroy (nh2);
	modifica_interval (nh1);
	return nh1;
}

void modifica_interval (int nh)
{
	pozsupdate = PS[nh];
	pozdupdate = PD[nh];
	valupdate = nh;
	update (1, 1, N);
}

int main ()
{
	freopen ("hotel.in", "r", stdin);
	freopen ("hotel.out", "w", stdout);
	
	scanf ("%d%d", &N, &M);
	initializari ();
	while (M --)
	{
		scanf ("%d", &tip);
		if (tip == 1)
		{
			citeste ();
			
			if (AI[nodmargin1] == 0 && AI[nodmargin2] == 0)
			{
				destroy (AI[nodinterior]);
			}
			else if (AI[nodmargin1] == 0)
			{
				shrink_right (AI[nodmargin2]);
			}
			else if (AI[nodmargin2] == 0)
			{
				shrink_left (AI[nodmargin1]);
			}
			else
			{
				split (AI[nodinterior]);
			}
			
			pozsupdate = pozs;
			pozdupdate = pozd;
			valupdate = 0;
			update (1, 1, N);
		}
		else if (tip == 2)
		{
			citeste ();
			
			if (AI[nodmargin1] == 0 && AI[nodmargin2] == 0)
			{
				nodinterior = create ();
			}
			else if (AI[nodmargin1] == 0)
			{
				nodinterior = xpand_right (AI[nodmargin2]);
			}
			else if (AI[nodmargin2] == 0)
			{
				nodinterior = xpand_left (AI[nodmargin1]);
			}
			else
			{
				nodinterior = merge (AI[nodmargin1], AI[nodmargin2]);
			}
			
			update (1, 1, N);
		}
		else
		{
			printf ("%d\n", PD[H[1]] - PS[H[1]] + 1);
		}		
	}
	
	return 0;
}