Cod sursa(job #1748019)

Utilizator MihaiAlinGrigoreMihaiAlin MihaiAlin Data 25 august 2016 22:49:26
Problema Lupul Urias si Rau Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.74 kb
/* descriere lupu
Se construieste vectorul Ti care retine timpul maxim la care oaia i poate fi aleasa si notam T_max valoarea
maxima din T.
O abordare care insa nu conduce la punctaj maxim este programarea dinamica, calculand soli,j cantitatea maxima
de lana care se poate alege cu primele i oi pana la momentul j. Raspunsul se va gasi in soln,T_max.
Complexitatea este O(n2) si ar obtine aproximativ 50-60 de puncte.
O rezolvare ce aduce 100 de puncte se bazeaza pe metoda greedy. Pentru fiecare valoare j de la T_max la 1 se
adauga intr-o multime toate cantitatile de lana Ai pentru oile cu Ti=j, apoi se extrage valoarea maxima care
se adauga la solutie, restul valorilor pastrandu-se in multime pentru pasul urmator. Atentie, se va extrage
valoarea maxima chiar daca la acest pas nu s-au introdus valori noi in multime. Pentru a implementa eficient
aceste operatii ne vom folosi un heap care suporta operatiile de extragere maxim si adaugare element in
O(log n). Complexitatea finala a algoritmului va fi de O(n log n).
Demonstratia intuitiva a faptului ca algoritmul conduce la solutie optima este ca la fiecare pas j se alege
valoarea maxima dintre cele care nu vor mai putea fi alese la pasul j+1.
O alta solutie tot greedy a problemei este sortarea descrescatoare dupa cantitatile de lana.
Pentru fiecare valoare apoi se vede cel mai mare timp mai mic sau egal cu Ti si la care nu a mai fost
aleasa nici o alta oaie. Daca exista un astfel de timp se adauga valoare respectiva la solutie.
Acest lucru se poate realiza cu o cautare binara a acestui timp. O alternativa la acest lucru ar fi folosirea
multimilor disjuncte. Initial se considera fiecare moment de timp o multime. Notam X = minimul din multimea
care il contine pe Ti. Daca alegem Ai pentru a-l adauga la solutie se va reuni multimea care il contine pe X
cu multimea care il contine pe X-1. Aceasta rezolvare insa este considerata peste nivelul mediu al clasei a
9-a.
*/
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
int n,i,j,p,q,nr,l,x,lv,Max;
struct nod
{
    int x;
    int y;
}v[100005];
priority_queue< int >Q;
long long sol;
int cmp(const nod a,const nod b)
{
    return a.x>b.x;
}
int main()
{
    freopen("lupu.in","r",stdin);
    freopen("lupu.out","w",stdout);
    scanf("%d %d %d",&n,&x,&l);
    for (i=1;i<=n;i++)
    {
        scanf("%d %d",&p,&q);
        if (p<=x)
        {
            v[++lv].x=(x-p)/l;
            v[lv].y=q;
            Max=max(Max,(x-p)/l);
        }
    }
    sort(v+1,v+lv+1,cmp); p=1;
    for (i=Max;i>=0;i--)
    {
        while (v[p].x==i)
        Q.push(v[p].y),p++;
        if (Q.size())
        {
            sol+=Q.top();
            Q.pop();
        }
    }
    printf("%lld",sol);
    return 0;
}