Rezolvare completă PbInfo #678 mts

Alex a accesat fonduri europene și a pus bazele unei afaceri profitabile, constând în creșterea viermilor de mătase. Viermii de mătase se hrănesc cu frunze de dud, iar Alex are mulți duzi în grădină. El a observat că dacă așează un vierme de mătase pe o frunză de dud, acesta va mânca toată frunza într-un timp care depinde doar de mărimea suprafeței frunzei.

Alex a decis să le aplice viermilor săi de mătase un test de inteligență. În acest scop, a pus în practică următorul experiment științific: pe o bară îngustă, liniară, a așezat de la stânga la dreapta n frunze de dud având suprafețele s[1], s[2], … s[n], la distanțe x[1], x[2],…, x[n] milimetri față de capătul din stânga. Alex a așezat un vierme de mătase pe frunza cu numărul de ordine k. Pentru oricare frunză i, viermele de mătase va mânca frunza în s[i] secunde, unde s[i] este mărimea suprafeței frunzei. După ce mănâncă în întregime o frunză, viermele pornește imediat cu viteza de 1 milimetru/ secundă spre următoarea frunză, care poate fi la stânga sau la dreapta sa. Altfel spus, el își poate schimba dacă e cazul, sensul de deplasare după ce mănâncă o frunză.

Alex ar dori să știe care este numărul maxim de frunze de dud pe ar putea să le mănânce în întregime cel mai inteligent vierme de mătase pe care îl are, având la dispoziție timpul de maxim t secunde.

Cerința

Cunoscând n, k, t, distanțele x[1], x[2], .., x[n] și suprafețele s[1], s[2], …, s[n] cu semnificațiile descrise mai sus, să se determine numărul maxim de frunze pe care un vierme de mătase poate să le mănânce în întregime, într-un timp cel mult egal cu t, dacă este plasat inițial pe frunza k.

Date de intrare

Fişierul de intrare mts.in conţine pe prima linie trei numere naturale n k t separate prin câte un spaţiu, cu semnificația descrisă anterior.

Pe linia a doua se află n numere naturale s[1] s[2] ... s[n] separate prin câte un spațiu, reprezentând mărimea suprafețelor celor n frunze.

Pe linia a treia se găsesc se găsesc n numere naturale x[1] x[2] ... x[n] separate prin câte un spațiu, reprezentând distanțele la care sunt așezate cele n frunze de dud față de capătul din stânga a barei.

Date de ieșire

Pe prima linie a fişierului mts.out se va scrie un singur număr natural f reprezentând numărul maxim de frunze care pot fi mâncate de către cel mai inteligent vierme de mătase în timpul t.

Restricții și precizări

  • 1 ≤ k ≤ n ≤ 200 000
  • 1 ≤ s[1], s[2], ..., s[n] ≤ 1000
  • 1 ≤ x[1] < x[2] < ... < x[n] ≤ 1 000 000
  • 1 ≤ t ≤ 2 000 000
  • Imediat cum ajunge la poziția în care se găsește o frunză de dud, viermele se oprește și începe să mănânce acea frunză. Nu va pleca din acea poziție până când frunza nu va fi mâncată în întregime.

Exemplu

mts.in

3 2 9
4 2 5
1 5 6

mts.out

2

Explicație

Viermele va mânca 2 frunze: cele cu numerele de ordine 2 și 3. Timpul total va fi:
s[2] + s[3] + (x[3] – x[2]) = 2 + 5 + 1 = 8

Dacă ar încerca să mănânce frunzele 2 și 1, atunci timpul total ar fi:
s[2] + s[1] + (x[2] – x[1]) = 2 + 4 + (5 – 1) = 10 > 9


Exemplu

mts.in

4 2 11
4 2 1 5
1 2 4 8

mts.out

3

Explicație

Viermele va mânca 3 frunze: cele cu numerele de ordine 2, 1 și 3, exact în această ordine, în timpul total:
s[2] + s[1] + s[3] + 2*(x[2]–x[1]) + (x[3]-x[2]) = 2 + 1 + 4 + 2*(2 – 1) + (4 – 2) = 11

Cum e corect?

cout < "As la info"; cout << "As la info"; cout >> "As la info";

Felicitări! Poți mai mult?

Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.

Greșit, dar nu-i bai!

Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.

Rezolvare

Iată rezolvarea de 100 de puncte pentru problema mts:

/* Solutie 100 puncte
   Prof. Constantin Galatan
   Complexitate: O(n * log n)
*/
#include <fstream>
#include <algorithm>
#include <vector>
using namespace std;

ifstream fin("mts.in");
ofstream fout("mts.out");

const int Dim = 1000010;
short a[Dim];
int x[Dim];
int s[Dim];
int T, N, K, Nmax;
int t, cnt, cnt1;

void Read();
void Solve();
void BSL();
void BSR();

int main()
{
    Read();
    Solve();
    fout << Nmax << '\n';

    fout.close();
}

void Solve()
{
    if ( a[K] > T ) return;
    // merg spre dreapta
    for ( int i = K; t <= T && i <= N; ++i )
    {
        if ( a[i] > T ) break;
        t = a[K] + (x[i] - x[K]) + (s[i] - s[K]);
        if ( t <= T )
        {
            cnt = i - K + 1;
            Nmax = max(Nmax, cnt);
            if ( t + (x[i] - x[K]) <   T ) // pot face drumul inapoi pana la T
            {
                t += (x[i] - x[K]);
                cnt1 = 0;
                if ( t < T )
                    BSL();
                Nmax = max(Nmax, cnt + cnt1);

            }
        }
    }
    t = 0;
    // merg spre stanga
    for ( int i = K ; t <= T && i >= 1; --i )
    {
        if ( a[i] > T ) break;
        t = a[K] + (x[K] - x[i]) + (s[K - 1] - s[i - 1]);
        if ( t <= T )
        {
            cnt = K - i + 1;
            Nmax = max(Nmax, cnt);
            if ( t + (x[K] - x[i]) <   T ) // pot face drumul inapoi pana la T
            {
                t += (x[K] - x[i]);
                cnt1 = 0;
                if ( t < T )
                    BSR();
                Nmax = max(Nmax, cnt + cnt1);
            }
        }
    }
}

void Read()
{
    fin >> N >> K >> T;
    for (int i = 1; i <= N; ++i )
    {
        fin >> a[i];
        s[i] = s[i - 1] + a[i];
    }
    for (int i = 1; i <= N; ++i )
        fin >> x[i];
    fin.close();
}

void BSR()
{
    int lo = K + 1, hi = N, mid;
    while ( lo <= hi )
    {
        mid = lo + ( hi - lo ) / 2;
        if ( t + x[mid] - x[K] + s[mid] - s[K] <= T )
        {
            cnt1 = mid - K;
            lo = mid + 1;
        }
        else
            hi = mid - 1;
    }
}

void BSL()
{
    int lo = 1, hi = K - 1, mid;
    while ( lo <= hi )
    {
        mid = lo + ( hi - lo ) / 2;
        if ( t + x[K] - x[mid] + s[K - 1] - s[mid - 1] <= T )
        {
            cnt1 = K - mid;
            hi = mid - 1;
        }
        else
            lo = mid + 1;
    }
}

Atenție

Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa Adresa de email.

Rezolvarea problemei #678 mts

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #678 mts de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.

Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!