#include <stdio.h>
#include <stdlib.h>
typedef struct{
int inaltime, 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].inaltime < v[j].inaltime) v[contor++] = aux[i++];
else
if (v[j].inaltime < aux[i].inaltime) 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;
}
// Functie care cauta minimul dintr-un sir
void search_min(int *v, int *min_ind, int *min, int j)
{
int i;
for (i = 0; i < j; i++)
if (*min > v[i]) {*min = v[i]; *min_ind = i;}
}
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)].inaltime == 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;
}
}
}
}
int main()
{
FILE *in = NULL, *out = NULL;
int n, h, u, i, suma = 0, sf_heap = 0, inc_vector = 0, inaltime;
// 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 (inaltime div u, greutate),
// sortate descrescator dupa inaltime div u, iar in cazul egalitatii dupa greutate
fscanf(in, "%i %i %i",&n, &h, &u);
Gutui gutui[n], aux2;
int aux[n];
for (i = 0; i < n; i++)
{
fscanf(in, "%i %i", &(gutui[i].inaltime), &(gutui[i].greutate));
gutui[i].inaltime = (gutui[i].inaltime - 1)/u;
}
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
inaltime = gutui[0].inaltime;
for (; inaltime < h/u; inaltime++)
{
insert_heap(gutui, inaltime, &sf_heap, &inc_vector, n);
suma +=gutui[0].greutate;
for (gutui[0] = gutui[--sf_heap], i = 0; i < sf_heap;)
{
if (gutui[2*i+1].greutate < gutui[2*i+2].greutate)
{
aux2 = gutui[2*i+2];
gutui[2*i+2] = gutui[i];
gutui[i] = aux2;
i = 2*i+2;
}
else
{
aux2 = gutui[2*i+1];
gutui[2*i+1] = gutui[i];
gutui[i] = aux2;
i = 2*i+1;
}
}
}
fprintf(out,"%i", suma);
fclose(in);
fclose(out);
return 0;
}