#include <stdio.h>
#include <stdlib.h>
typedef struct{
int nivel, greutate;
} Gutui;
// Functii pentru merge sort
void merge(Gutui *v, Gutui *aux, int inceput, int sfarsit, int mijloc, int u)
{
int i, j = mijloc, contor = inceput;
for (i = inceput; i < mijloc; i++)
aux[i] = v[i];
i = inceput;
while (i < mijloc && j < sfarsit)
if (aux[i].nivel > v[j].nivel) v[contor++] = aux[i++];
else
if (v[j].nivel > aux[i].nivel) v[contor++] = v[j++];
else
if (aux[i].greutate > v[j].greutate) v[contor++] = aux[i++];
else
v[contor++] = v[j++];
for (;i < mijloc; v[contor++] = aux[i++]);
return;
}
void merge_sort_aux(Gutui *v, Gutui *r, int i, int j, int u)
{
if (j-i == 1) return;
int m = (i + j) / 2;
merge_sort_aux(v, r, i, m, u);
merge_sort_aux(v, r, m, j, u);
merge(v, r, i, j, m, u);
}
int merge_sort(Gutui *v, int i, int j, int u)
{
Gutui *aux = (Gutui*)malloc(j * sizeof(Gutui));
if(!aux) return 0;
merge_sort_aux(v, aux, i, j, u);
free(aux);
return 1;
}
// Inserez in heap toate gutuile de pe nivelul inalt
void insert_heap(Gutui *v, int inalt, int *sf_heap, int *inc_vector, int n)
{
int i = 0, j;
Gutui aux;
for (; (*inc_vector) < n && v[(*inc_vector)].nivel == inalt;(*inc_vector)++, (*sf_heap)++)
{
v[(*sf_heap)] = v[(*inc_vector)];
for (i = (*sf_heap);i > 0; i = j)
{
j = (i-1)/2;
if (v[j].greutate < v[i].greutate) { aux = v[i];
v[i] = v[j];
v[j] = aux;
}
else break;
}
}
}
int main()
{
FILE *in = NULL, *out = NULL;
int n, h, u, i, suma = 0, sf_heap = 0, inc_vector = 0, inaltime = 0;
// Deschiderea fisierelor
in = fopen("gutui.in", "rt");
out = fopen("gutui.out", "wt");
if (!in || !out) {printf("Eroare la deschiderea fisierelor"); return -1;}
// Citesc datele din fisier si introduc gutuile intr-un vector de perechi (numarul de gutui care trebuiesc luate ca sa nu se mai ajunga, greutate),
// sortate descrescator dupa nivel, iar in cazul egalitatii dupa greutate
fscanf(in, "%i %i %i",&n, &h, &u);
if (!n) {fprintf(out, "0");fclose(in); fclose(out); return 0;}
Gutui gutui[n], aux;
for (i = 0; i < n; i++)
{
fscanf(in, "%i %i", &(gutui[i].nivel), &(gutui[i].greutate));
gutui[i].nivel = (h - gutui[i].nivel)/u + 1;
}
merge_sort(gutui, 0, n, u);
// Parcurg tot vectorul culegand mereu prima gutuie gasita cu (inaltimea + nr_gutui_culese * u) < h
// Daca gasesc gutui neculese mai mari decat minimul dintre cele culese, o culeg pe aceasta in locul minimului
h = h/u;
inaltime = gutui[0].nivel;
for (; inaltime > 0; inaltime--)
{
insert_heap(gutui, inaltime, &sf_heap, &inc_vector, n);
if (sf_heap)
{
suma +=gutui[0].greutate;
for (gutui[0] = gutui[--sf_heap], i = 0; i < sf_heap;)
{
if (2*i+1 < sf_heap && 2*i+2 < sf_heap)
{
if (gutui[2*i+1].greutate < gutui[2*i+2].greutate)
{
if (gutui[i].greutate > gutui[2*i+2].greutate) break;
aux = gutui[2*i+2];
gutui[2*i+2] = gutui[i];
gutui[i] = aux;
i = 2*i+2;
}
else
{
if (gutui[i].greutate > gutui[2*i+1].greutate) break;
aux = gutui[2*i+1];
gutui[2*i+1] = gutui[i];
gutui[i] = aux;
i = 2*i+1;
}
}
else
if (2*i+1< sf_heap && gutui[i].greutate < gutui[2*i+1].greutate)
{
aux = gutui[2*i+1];
gutui[2*i+1] = gutui[i];
gutui[i] = aux;
i = 2*i+1;
}
else break;
}
}
}
fprintf(out,"%i", suma);
fclose(in);
fclose(out);
return 0;
}