Cod sursa(job #2178084)

Utilizator 24601Dan Ban 24601 Data 19 martie 2018 05:36:34
Problema Heapuri Scor 100
Compilator c Status done
Runda Arhiva educationala Marime 3.81 kb
/**
 * References
 *
 * https://queue.acm.org/detail.cfm?id=1814327
 * http://phk.freebsd.dk/B-Heap/
 */
#include <stdint.h>
#include <stdio.h>

#define SIZE 200704

struct elem {
    int x, ins_time;
};

static unsigned h_psize, h_shift, h_mask, h_hmask, h_num_elem, h_algo;
static unsigned at_n;
static struct elem h[SIZE];
static int ins_time_to_h_pos[SIZE];

static inline unsigned h_po(unsigned idx)
{
    /* return offset inside page of element at idx */
	return (idx & h_mask);
}

static void h_bubble_up(unsigned idx, struct elem v)
{
	unsigned idx_of_parent, po;
	struct elem parent_value;

	while (idx > 1) {
	    if (h_algo == 1) {
	        idx_of_parent = idx >> 1;
	    } else {
		    po = h_po(idx);
		    if (idx < h_psize || po > 3) {
			    idx_of_parent = (idx & ~h_mask) | (po >> 1);
		    } else if (po < 2) {
			    idx_of_parent = (idx - h_psize) >> h_shift;
			    idx_of_parent += (idx_of_parent & ~h_hmask);
			    idx_of_parent |= h_psize / 2;
		    } else {
			    idx_of_parent = idx - 2;
		    }
		}

		parent_value = h[idx_of_parent];
		if (parent_value.x < v.x)
			return;
		h[idx_of_parent] = v;
		ins_time_to_h_pos[h[idx_of_parent].ins_time] = idx_of_parent;
		h[idx] = parent_value;
		ins_time_to_h_pos[h[idx].ins_time] = idx;
		idx = idx_of_parent;
	}
}

static void h_bubble_down(unsigned idx, struct elem v)
{
	unsigned i1, i2;
	struct elem v1, v2;

	while (idx < h_num_elem) {
	    if (h_algo == 1) {
	        i1 = i2 = idx << 1;
	        i2++;
	    } else {
		    if (idx > h_mask && !(idx & (h_mask - 1))) {
			    /* first two elements in nonzero pages */
			    i1 = i2 = idx + 2;
		    } else if (idx & (h_psize >> 1)) {
			    /* Last row of page */
			    i1 = (idx & ~h_mask) >> 1;
			    i1 |= idx & (h_mask >> 1);
			    i1 += 1;
			    i1 <<= h_shift;
			    i2 = i1 + 1;
		    } else {
			    i1 = idx + (idx & h_mask);
			    i2 = i1 + 1;
		    }
		}

		if (i1 != i2 && i2 <= h_num_elem) {
		    v1 = h[i1];
		    v2 = h[i2];
			if (v1.x < v.x && v1.x <= v2.x) {
			    h[i1] = v;
			    ins_time_to_h_pos[h[i1].ins_time] = i1;
				h[idx] = v1;
			    ins_time_to_h_pos[h[idx].ins_time] = idx;
				idx = i1;
			} else if (v2.x < v.x) {
			    h[i2] = v;
			    ins_time_to_h_pos[h[i2].ins_time] = i2;
				h[idx] = v2;
			    ins_time_to_h_pos[h[idx].ins_time] = idx;
				idx = i2;
			} else {
				break;
			}
		} else if (i1 <= h_num_elem) {
		    v1 = h[i1];
			if (v1.x < v.x) {
			    h[i1] = v;
			    ins_time_to_h_pos[h[i1].ins_time] = i1;
			    h[idx] = v1;
			    ins_time_to_h_pos[h[idx].ins_time] = idx;
				idx = i1;
			} else {
				break;
			}
		} else
			break;
	}
}

static void h_insert(unsigned val)
{
	h_num_elem++;
	at_n++;
	h[h_num_elem].ins_time = at_n;
	h[h_num_elem].x = val;
	ins_time_to_h_pos[at_n] = h_num_elem;
	h_bubble_up(h_num_elem, h[h_num_elem]);
}

static void h_remove(unsigned ins_time)
{
	h[ins_time_to_h_pos[ins_time]] = h[h_num_elem];
    ins_time_to_h_pos[h[h_num_elem].ins_time] = ins_time_to_h_pos[ins_time];

	h_num_elem--;
	if (h_num_elem == 0)
		return;

	h_bubble_down(ins_time_to_h_pos[ins_time], h[ins_time_to_h_pos[ins_time]]);
}

int main(void)
{
    int n = 0, ch, x;

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

	h_shift = 9;
	h_mask = 511;
	h_hmask = h_mask >> 1;
	h_num_elem = 0;
	h_psize = 512;
	h_algo = 1;

    while ((ch = getchar()) != '\n') {
        n = n * 10 + ch - '0';
    }

    while (n--) {
        ch = getchar();
        getchar();
        x = 0;

        if (ch == '1') {
            while ((ch = getchar()) != '\n') {
                x = x * 10 + (ch - '0');
            }

            h_insert(x);
        } else if (ch == '2') {
            while ((ch = getchar()) != '\n') {
                x = x * 10 + (ch - '0');
            }

            h_remove(x);
        } else {
            printf("%d\n", h[1].x);
        }
    }

    return 0;
}