• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zadanie Wskaźnik Hirscha finał OIG

Object Storage Arubacloud
0 głosów
168 wizyt
pytanie zadane 14 maja 2023 w Algorytmy przez pasjonat_algorytmiki Pasjonat (19,540 p.)
edycja 14 maja 2023 przez pasjonat_algorytmiki

Mam problem z takim zadaniem: https://szkopul.edu.pl/problemset/problem/diIixmpgLnmLnihDYGeaDwYQ/site/?key=statement

Samo zadanie wydało mi się łatwe. Sortuje elementy od najmniejszych wymaganych publikacji i idę od góry zachłanem z setem, żeby naliczyć koszt[v] = min koszt biorąc A[v] elementów. I potem dla każdego zapytania się bin searchuję po kosztach. Napisałem kod i dostaję całą masę WA, i nie wiem, gdzie jest błąd:

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>

using namespace std;
typedef long long ll;

struct Element
{
    ll ile_cytowan;
    ll cena;
    bool operator < (const Element &element) const
    {
        return ile_cytowan < element.ile_cytowan;
    }
};

ll n = 0, q = 0;
ll suma = 0;
vector<Element> elementy;
vector<ll> koszty;
multiset<ll> S;

inline void napelniaj()
{
    koszty.assign(n,1e18+20);
    for (int i = n-1; i >= 0; --i)
    {
        suma += elementy[i].cena;
        S.insert(elementy[i].cena);
        while(S.size() > elementy[i].ile_cytowan)
        {
            ll val = *S.rbegin();
            suma -= val;
            S.erase(S.lower_bound(val));
        }
        if (S.size() == elementy[i].ile_cytowan)
            koszty[i] = suma;
    }
}

inline ll zapytanie()
{
    ll wartosc;
    cin >> wartosc;

    int poczatek = -1, koniec = n, srodek = 0;
    while(koniec - poczatek > 1)
    {
        srodek = (poczatek + koniec) / 2;
        if (wartosc >= koszty[srodek])
            poczatek = srodek;
        else
            koniec = srodek;
    }

    if (poczatek == -1)
        return 0;
    else
        return elementy[poczatek].ile_cytowan;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> q;

    elementy.assign(n,{});
    for (int i = 0; i < n; ++i)
        cin >> elementy[i].ile_cytowan >> elementy[i].cena;
    sort(elementy.begin(), elementy.end());

    napelniaj();

    while(q--)
        cout << zapytanie() << '\n';

    return 0;
}

Program zazwyczaj daje lekko za małe odpowiedzi.

edit: usunąłem jednego if-a w operatorze bo i tak nic nie dawał.

Z góry dziękuję za pomoc i poświęcony czas!

komentarz 14 maja 2023 przez pasjonat_algorytmiki Pasjonat (19,540 p.)
Chyba znalazłem błąd w pomyśle.

1 odpowiedź

0 głosów
odpowiedź 15 maja 2023 przez pasjonat_algorytmiki Pasjonat (19,540 p.)

Pomysł był dobry, tylko złe było założenie, ży wynik musi być wsród prac. Ważne spostrzerzenie jest takie, że wynik nie może być > n, ponieważ nie będzie dało się do ułożyć za pomocą n prac. Skoro N <= 2*10^5, to możemy sobie na spokojnie naliczyć koszt[v] dla każdego v >= 0 oraz v <= n. Znając to robimy praktycznie to samo. O(N lg N + Q lg N) - 100pkt:

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>

using namespace std;
typedef long long ll;

struct Element
{
    int ile_cytowan;
    int cena;
    bool operator < (const Element &element) const
    {
        return ile_cytowan < element.ile_cytowan;
    }
};

int n = 0, q = 0, wsk = 0;
ll suma = 0;
vector<Element> elementy;
vector<ll> koszty;
priority_queue<int> Q;

inline void napelniaj()
{
    koszty.assign(n+1,1e18+20);
    wsk = n-1;
    for (int i = n; i >= 0; --i)
    {
        while(wsk >= 0)
        {
            if (elementy[wsk].ile_cytowan >= i)
            {
                suma += elementy[wsk].cena;
                Q.push(elementy[wsk].cena);
                wsk--;
            }
            else
                break;
        }
        while(Q.size() > i)
        {
            ll val = Q.top();
            suma -= val;
            Q.pop();
        }
        if (Q.size() == i)
            koszty[i] = suma;
    }
}

inline ll zapytanie()
{
    ll wartosc;
    cin >> wartosc;

    int poczatek = 0, koniec = n+1, srodek = 0;
    while(koniec - poczatek > 1)
    {
        srodek = (poczatek + koniec) / 2;
        if (wartosc >= koszty[srodek])
            poczatek = srodek;
        else
            koniec = srodek;
    }
    return poczatek;
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> q;

    elementy.assign(n,{});
    for (int i = 0; i < n; ++i)
        cin >> elementy[i].ile_cytowan >> elementy[i].cena;
    sort(elementy.begin(), elementy.end());

    napelniaj();

    while(q--)
        cout << zapytanie() << '\n';

    return 0;
}

 

Podobne pytania

0 głosów
0 odpowiedzi 369 wizyt
pytanie zadane 16 maja 2023 w Algorytmy przez pasjonat_algorytmiki Pasjonat (19,540 p.)
0 głosów
2 odpowiedzi 351 wizyt
pytanie zadane 28 marca 2023 w Algorytmy przez pasjonat_algorytmiki Pasjonat (19,540 p.)
0 głosów
1 odpowiedź 152 wizyt
pytanie zadane 24 marca 2023 w Algorytmy przez pasjonat_algorytmiki Pasjonat (19,540 p.)

92,576 zapytań

141,426 odpowiedzi

319,652 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...