Cod sursa(job #1050640)

Utilizator rvnzphrvnzph rvnzph Data 8 decembrie 2013 21:15:31
Problema Heapuri Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.4 kb
//Min Heap
//Requires optimizations
//Get rid of swaps (too many)

#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)
{
	while(pos>1&&heap[ROOT(pos)]>heap[pos])
	{
		//current update is made on pos
		//pos <- ROOT(pos) (reads pos takes ROOT(pos) properties

		swap(heap[ROOT(pos)],heap[pos]);
		swap(at[at_1[ROOT(pos)]],at[at_1[pos]]);	//swap v[i], v[j]
		swap(at_1[ROOT(pos)],at_1[pos]);			//swap i, j

		pos=ROOT(pos);
	}
}

void sift(int pos)
{
	while(pos<=SIZE(heap))
	{
		int next;

		//get next element is this exists
		if(RIGHT(pos)<=SIZE(heap))
			heap[LEFT(pos)]<heap[RIGHT(pos)] ? next=LEFT(pos) : next=RIGHT(pos);
		else
		if(LEFT(pos)<=SIZE(heap))
			next=LEFT(pos);
		else return;

		//check if min-heap property is kept
		if(heap[pos]>heap[next])
		{
			swap(heap[pos],heap[next]);
			swap(at[at_1[pos]],at[at_1[next]]);
			swap(at_1[pos],at_1[next]);
			
			pos=next;
		}
		else return;
	}
}

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);

	if(pos<=SIZE(heap))		//check corectness of pos
							//case when the cut is made on the last element of the heap
		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;
}