Cod sursa(job #1050664)

Utilizator rvnzphrvnzph rvnzph Data 8 decembrie 2013 22:15:18
Problema Heapuri Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.9 kb
//Min Heap
//Simpified

#include <stdio.h>
#include <cstring>		//memset
#include <algorithm>	//swap

using namespace std;

#define heapLEN 200001

#define SIZE(v) v[0]

#define ROOT(x) (x>>1)
#define LEFT(x) (x<<1)
#define RIGHT(x) ((x<<1)+1)

					//val - imaginary array
					//val[i] = value of ith inserted element

int heap[heapLEN];	//min-heap structure

int at[heapLEN];	//at[i] = position y of ith inserted element in heap
					//at[i] = y
					//heap[y] = val[i]
					//heap[at[i]] = val[i]

int at_1[heapLEN];	//at_1[i] = position of the yth element from heap in at
					//at_1[y] = i
					//at_1 is the inverse function of at
					//at_1[at[i]] = at[at_1[i]] = i

void percolate(int pos)
{
	//keep auxiliaries because all swaps had one common variable
	int aux_heap=heap[pos];
	int aux_at=at[at_1[pos]];
	int aux_at_1=at_1[pos];

	//check is made on aux_heap (preserved value)
	while(pos>1&&heap[ROOT(pos)]>aux_heap)
	{
		//pos <- ROOT(pos) (reads pos takes ROOT(pos) properties

		heap[pos]=heap[ROOT(pos)];
		//at[at_1[pos]]=at[at_1[ROOT(pos)]];
		swap(at[at_1[pos]],at[at_1[ROOT(pos)]]);
		//at_1[pos]=at_1[ROOT(pos)];
		swap(at_1[pos],at_1[ROOT(pos)]);

		pos=ROOT(pos);
	}

	heap[pos]=aux_heap;
	//at[at_1[pos]]=aux_at;
	//at_1[pos]=aux_at_1;
}

void sift(int pos)
{
	int aux_heap=heap[pos];
	int aux_at=at[at_1[pos]];
	int aux_at_1=at_1[pos];

	int next=0;

	//use break instead of return because it is required
	//to place aux variables in required arrays
	while(pos<=SIZE(heap))
	{
		//get next element is this exists
		if(RIGHT(pos)<=SIZE(heap) && heap[RIGHT(pos)]<heap[LEFT(pos)]) next=RIGHT(pos);
		else
		if(LEFT(pos)<=SIZE(heap)) next=LEFT(pos);
		else break;

		//check if min-heap property is kept
		//check is made on aux_heap the preserved value
		if(aux_heap>heap[next])
		{
			heap[pos]=heap[next];
			at[at_1[pos]]=at[at_1[next]];
			at_1[pos]=at_1[next];
			
			pos=next;
		}
		else break;
	}

	if(next)
	{
		heap[pos]=aux_heap;
		at[at_1[pos]]=aux_at;
		at_1[pos]=aux_at_1;
	}
}

void insert(int val)
{
	//SIZE(heap) = SIZE(at_1)
	//thinking of at, at_1 as functions then
	//at: A -> B
	//at_1: B -> A
	//card(A) = card(B) (must)
	//in code: SIZE(heap) != SIZE(at) (not always)
	//in reality: SIZE(heap) == SIZE(at) (always)
	
	++SIZE(heap);

	heap[SIZE(heap)]=val;

	++SIZE(at);
	at[SIZE(at)]=SIZE(heap);
	at_1[SIZE(heap)]=SIZE(at);

	percolate(at[SIZE(at)]);
}

void cut(int pos)
{
	//pos = at[i]
	//SIZE(heap) = at[x]
	//apply inverse function on the previous equations
	//i = at_1[pos]
	//x = at_1[SIZE(heap)]
	
	swap(heap[pos],heap[SIZE(heap)]);
	swap(at[at_1[pos]],at[at_1[SIZE(heap)]]);
	swap(at_1[pos],at_1[SIZE(heap)]);

	//after the swap the last element in the heap is not needed anymore
	//0 in at array means that element is not in use
	//SIZE(at) - COUNT(0s in at) = SIZE(heap)
	heap[SIZE(heap)]=0;
	at[at_1[SIZE(heap)]]=0;
	at_1[SIZE(heap)]=0;

	--SIZE(heap);

	//check corectness of pos
	//case when the cut is made on the last element of the heap
	if(pos>SIZE(heap)) return;

	//pos has a valid value
	if(pos>1&&heap[ROOT(pos)]>heap[pos]) percolate(pos);
	else sift(pos);
}

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

	memset(heap,0,sizeof(heap));
	memset(at,0,sizeof(at));
	memset(at_1,0,sizeof(at_1));

	int N;
	scanf("%d",&N);

	while(N--)
	{
		int cod;
		scanf("%d",&cod);

		switch(cod)
		{
			case 1:
				int val;
				scanf("%d",&val);
				insert(val);
				break;
			case 2:
				int i;
				scanf("%d",&i);
				cut(at[i]);
				break;
			case 3:
				printf("%d\n",heap[1]);
				break;
		}

		///***DEBUG***
		if(cod!=3)
		{
			printf("SIZE(heap) = %d\n",SIZE(heap));
			printf("SIZE(at) = %d\n",SIZE(at));
			printf("heap : ");
			for(int i=1;i<=SIZE(heap);++i)
				printf("%d ",heap[i]);
			printf("\nat : ");
			for(int i=1;i<=SIZE(at);++i)
				printf("%d ",at[i]);
			printf("\nat_1 : ");
			for(int i=1;i<=SIZE(heap);++i)
				printf("%d ",at_1[i]);
			printf("\n\n");
		}
		//*/
	}

	return 0;
}