Cod sursa(job #677141)

Utilizator lxnchPopescu Ion lxnch Data 9 februarie 2012 21:25:22
Problema Heapuri Scor 40
Compilator c Status done
Runda Arhiva educationala Marime 3.91 kb
#include <stdio.h>
#include <stdlib.h>

#define MAXOP 5000000
const unsigned int maxelem = 1000000000;
int pozIntrare[MAXOP];
int pozHeap[MAXOP], poz;
unsigned int heap[MAXOP];
unsigned int nrIntrari;

void afiseaza(unsigned int *heap, unsigned int dim) {
	unsigned int i=0;
	for(;i<dim; i++) {
		printf("%u ", heap[i]);
	}
	printf("\n");
}

//void refaHeap(unsigned int *heap, unsigned int start, unsigned int stop){
void refaHeap(unsigned int *heap, unsigned int start, unsigned int stop){
	unsigned int index=start;
	short int eHeap=0;
	unsigned int temp;

	while((2*index+1 < stop) && !eHeap) {
		unsigned int copil = 2*index+1;
		if ((copil < stop-1) && (heap[copil] > heap[copil+1])) copil++;
		if (heap[index] > heap[copil]) {
			temp = heap[index]; heap[index] = heap[copil]; heap[copil] = temp;
			pozHeap[heap[index]] = index;
			pozHeap[heap[copil]] = copil;
			index = copil;
		}
		else {
			pozHeap[heap[index]] = index;
			pozHeap[heap[copil]] = copil;
			eHeap=1;
		}
	}

	pozHeap[heap[2*index]]=2*index;
}

void insereaza(unsigned int *heap, unsigned int *dim, int elem) {
	//daca heap-ul e gol, punem elementul ca radacina si incrementam contorul nrelem;
	if (*dim == 0 ) {
		heap[0] =elem;
		*dim+=1;
		pozIntrare[nrIntrari++]=elem;
		pozHeap[elem]=0;
	}
	else if (*dim < maxelem) {
		*dim+=1; // facem loc pentru noul element
		heap[*dim-1]=elem; //pun elementul de inserat pe ultima pozitie din heap
		pozIntrare[nrIntrari++]=elem;
		int i=(*dim-1)/2;
		//refac heap-ul
		//printf("Vrei sa inserez elem %d\n", elem);
		for(;i>=0; i--)
			refaHeap(heap, i, *dim);
		//printf("Pozitia finala: %d (pt elem %d)\n", pozHeap[elem],elem);
	}
	else // am umplut heap-ul
		return;
}

void percolate(unsigned int *heap, unsigned int *dim, unsigned int pozitie) {
}

void elimina(unsigned int *heap, unsigned int *dim, unsigned int pozelem) {
	// intai luam elementul care-a fost inserat pe pozitia respectiva
	int elem = pozIntrare[pozelem-1];
	if(elem == -1) return;
	unsigned int i;
	i=pozHeap[elem];
	//printf("Inainte de stergere: ");afiseaza(heap, *dim); printf(" dim=%u", *dim);
	//printf("Vrei sa-l elimin pe %u (poz %u in heap)\n", elem, pozHeap[elem]);
	//gasesc pozitia in heap a elementului pe care vreau sa-l elimin
	if(i == -1) return; // a fost deja eliminat..
	heap[i] = heap[*dim-1];
	*dim-=1;
	//int j=(*dim-1)/2;
	//refac heap-ul
	//for(;j>=0; j--)
	//	refaHeap(heap, j, *dim,-1);
	//printf("Dupa swap: ");afiseaza(heap, *dim); printf(" dim=%u", *dim);
	//printf("Copil: %u Tata: %u\n", heap[i], heap[i/2]);
	if ((i>1) && heap[i] < heap[i/2]) {
		//printf("percolam!\n");
		percolate(heap, dim, i);
	}
	else {
		//printf("cernem!\n");
		refaHeap(heap,i,*dim);
	}
	pozIntrare[pozelem-1]=-1;
	//printf("Eliminat!\n");
	//printf("Dupa stergere: ");afiseaza(heap, *dim);
}

int main() {
	//FILE *fisin, *fisout;
	unsigned int c1, c2, nrop, nrelem=0;
	int l;
	freopen("heapuri.in", "r", stdin);
	freopen("heapuri.out", "w", stdout);

	//if ((fisin = fopen("heapuri.in", "r")) == NULL)
	//exit(1);
	//if ((fisout = fopen("heapuri.out", "w")) == NULL)
//		exit(1);

	scanf("%u", &nrop);
	if (nrop > MAXOP && 1 <= nrop) // 1<= N<=200.000
		exit(1);

	for(l=1;l<=nrop;l++) {
		scanf("%u", &c1);

		switch (c1) {
		case 1:
			scanf("%u", &c2);
			//inserez elementul c2 in heap
			if (c2 > maxelem || c2 < 1)
				exit(1);
			insereaza(heap, &nrelem, c2);
			break;
		case 2:
			scanf("%u", &c2);
			//sterg elementul de pe pozitia specificata de c2
			if (c2 > maxelem || c2 < 1)
				exit(1);
			elimina(heap, &nrelem, c2);
			//afiseaza(heap, nrelem);
			break;
		case 3:
			//afisez elementul minim din heap, adica radacina
			printf("%u\n", heap[0]);
			break;
		default:
			exit(1);
			break;
		}
	}
	//afiseaza(pozIntrare, nrIntrari);
	//printf("Total elemente: %u\n", nrelem);
	//fclose(fisin);
	//fclose(fisout);
	return 0;
}