#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DEBUG 0
typedef struct gutuie{
int greut;//ce greutate are
int inalt;//la ce inaltime
int rez;//cate gutui maxim pot culege inainte sa nu mai ajung la aceasta gutuie
//altfel spus, ce rezistenta are :P
}gutuie;
struct node
{
int priority;
int info;
struct node *next;
}*start,*q,*temp,*noul;
typedef struct node *N;
//functia de insertie
void insert(int itprio)
{
noul=(struct node *)calloc(1,sizeof(struct node));
noul->priority=itprio;
if(start==NULL || itprio<start->priority)
{
noul->next=start;
start=noul;
}
else
{
q=start;
while(q->next != NULL && q->next->priority<=itprio)
q=q->next;
(noul->next)=(q->next);
q->next=noul;
}
}
int peek()
{
if(start==NULL)
return 0;
else
return start->priority;
}
//delete
void del()
{
if(start==NULL)
{
printf("\n eroare");
}
else
{
noul = start;
start=start->next;
free(noul);
}
}
void swap (gutuie *a, gutuie *b)
{
gutuie c = *a;
*a = *b;
*b = c;
}
//sortare gutui, mergesort
void qsort_r (gutuie* primul, gutuie* ultimul)
{
gutuie *mic = primul;
gutuie *mare = ultimul;
gutuie pivot = *(primul+(ultimul-primul)/2);
while (mic <= mare)
{
while ((*mic).rez < pivot.rez || ((*mic).rez == pivot.rez && (*mic).greut > pivot.greut) ) mic++;
while (pivot.rez < (*mare).rez || (pivot.rez == (*mare).rez && pivot.greut > (*mare).greut)) mare--;
if (mic < mare) swap (mic++, mare--);
else mic++;
}
if (primul < mare)
qsort_r (primul, mare);
if (mare < ultimul)
qsort_r (mare+1, ultimul);
}
int main()
{
FILE *input;
FILE *output;
int i,j,m,n;
//nr gutui, inaltimea, si cu cat se ridica
int Nr,H,U;
int *inaltimi;
int *greutati;
int *rezista;
gutuie *vec;
int rezultat=0;
int remains;
int alese;
int nr_gutui;
int diferenta,nivel,niv_curent,alesi_pe_nivel;
//citirea datelor
input = fopen("gutui.in","r");
fscanf(input,"%d %d %d",&Nr,&H,&U);
//cate un vector pentru fiecare
inaltimi = (int*)calloc(Nr,sizeof(int));
greutati = (int*)calloc(Nr,sizeof(int));
rezista = (int*)calloc(Nr,sizeof(int));
//un vector de gutui
vec = (gutuie*)calloc(Nr,sizeof(gutuie));
start = NULL;
//citesc inaltimile si greutatile
for(i=0;i<Nr;i++){
fscanf(input,"%d %d",&(vec[i].inalt),&(vec[i].greut));
}
fclose(input);
//calculez fiecare gutuie la cate culegeri ( de alte gutui ) rezista
for(i=0;i<Nr;i++)
vec[i].rez = (H-vec[i].inalt)/U+1;
//sortez gutuile in functie de rezistenta (primar) si apoi de greutate(pt rezistente egale)
qsort_r(vec,vec+Nr-1);
if(DEBUG)
for(i=0;i<Nr;i++)
printf("%d %d %d\n", vec[i].greut,vec[i].rez,vec[i].inalt);
remains = 0;
nivel = vec[0].rez;
niv_curent = nivel;
if(DEBUG)printf("incep");
//inserez primele gutui, cele care nu rezista deloc, in coada prioritara
//din aceste gutui am voie sa aleg maxim una
alesi_pe_nivel=0;
for(i=0;i<nivel&&vec[i].rez==nivel;i++){
alesi_pe_nivel+=1;
insert(vec[i].greut);
}
diferenta =0;
alese=alesi_pe_nivel;
//iterez pe toate gutuile
for(i=alesi_pe_nivel;i<Nr;i++)
{
if(DEBUG)display();
if(DEBUG)printf("\n-%d- %d %d\n",i,vec[i].greut,vec[i].rez);
//daca am trecut la alt nivel
if(vec[i].rez > nivel)
{
niv_curent = vec[i].rez;
//am voie sa aleg maxim diferenta dintre acest nivel si penultimul
//gutui
diferenta = niv_curent - alese;
nivel=niv_curent;
//aleg pe cea mai grea
insert(vec[i].greut);
alese+=1;
//diferenta scade cu 1
diferenta -=1;
//am ales o gutuie pe acest nivel
alesi_pe_nivel =1;
}
else
{//daca mai am inca loc sa aleg gutui de pe acest nivel, aleg pe cea mai grea
if(diferenta>0){
insert(vec[i].greut);
alese+=1;
diferenta -=1;
alesi_pe_nivel+=1;
}
else
{ //altfel, pentru restul de gutui de pe acest nivel, ma uit sa vad daca sunt mai grele
//decat vreo gutuie aleasa de pe un nivel anterior, caz in care fac schimb
//aici ma ajuta coada prioritara, pentru ca ma uit direct la cele mai usoare gutui alese
if(alesi_pe_nivel < niv_curent){
if(peek() < vec[i].greut){
del();
insert(vec[i].greut);
alesi_pe_nivel+=1;
}
}
}
}
}
diferenta =0;
//calculez greutatea finala
while(start != NULL)
{
diferenta += peek();
del();
}
output=fopen("gutui.out","w");
fprintf(output,"%d",diferenta);
fclose(output);
//getchar();
return 0;
}