Zadanie Malowanie płotu w c++

0

screenshot-20240603220822.png

#include <iostream>
using namespace std;

int main()
{
    unsigned int n,m,wybor,l,r,a;
    cin >> n >> m;      
    int deski[n]={0};  //tablica niepomalowanych desek
    
    if((1 <= n && n <= 100000) && (1 <= m && m <= 100000))  //if sprawdzający założenia podane w tekście
    {
        for(int i = 0; i < m; i++)
        {
            do cin >> wybor;                        //wybieramy 1-malowanie czy 2-liczenie warstw, jeśli spoza zakresu to powtórz
            while(wybor != 1 && wybor != 2); 
            
            switch (wybor)
            {
            case 1:
                cin >> l >> r;
                if((1 <= l && l <= n) && (1 <= r && r <= n))  //if sprawdzający założenia podane w tekście
                {
                    for(l; l <= r; l++) //dodajemy warstwe do każdej deski w podanym zakresie
                    {
                        deski[l-1]++;
                    }
                }
                break;
                
            case 2:
                cin >> a; //wyświetlamy ile warstw ma konkretna deska
                cout << deski[a-1] << endl; 
                break;
            }
        }
    }
    return 0;
}

Testując kod na stronie, z której wziąłem to zadanie na 40 testów 7 kończy się przekroczeniem limitu czasu (1 s). Zastanawiam się jak mogę przyspieszyć dodawanie warstw do desek (bo jedynie tu widze problem).

2

Ustawa wskaźnik na pierwszą deskę którą będzie dzisiaj malował, a potem przesuń go na następny element tablicy. Dzięki temu nie trzeba będzie za każdym razem liczyć gdzie jest element tablicy o numerze x

0

Treść zadania jest tak durna że nie mogę jej czytać. Naprawde chciałbym pomóc, ale osobiście najlepszą pomocą dla tego Bajtka to oddanie go do szpitala psychiatrycznego. A następnie tego co takie zadania wymyśla. Kto liczy jakieś warstwy farby w płocie xDD???

2

Nieco offtopic, ale lepiej nakierować początkującego na włściwe tory:

Zacznij od przepisania kodu tak by rozdzielić operacje IO od samego problemu.
Następnie zainteresuj się pisaniem testów jednostkowych - ważna umiejętność, która bardzo pomaga w przypadku takich zadań.
Jak będziesz miał dobrze podzielony kod, to wtedy dopisanie testów jednostkowych będzie łatwe.

Przykład z użyciem Catch2

#include "catch2/catch_all.hpp"

struct WorkDay {
    int start; // when start is 0 couting layaers for stop
    int stop;
};

constexpr int CountLayers = 0;

std::vector<int> countLayersOfPaintFor(int plankCount, const std::vector<WorkDay>& workDays)
{
    // TODO: provide implmentation here
    (void)plankCount;
    (void)workDays;
    return {};
}

//-------------test---------------

std::ostream& operator<<(std::ostream& out, const WorkDay& d)
{
    if (d.start == CountLayers) {
        return out << "(Count:" << d.stop << ')';
    } else {
        return out << "(Paint:" << d.start << '-' << d.stop << ")";
    }
}

TEST_CASE("Fance paiting")
{
    auto [plankCount, workPlan, expectedResult] = GENERATE(table<int, std::vector<WorkDay>, std::vector<int>>({
        // simple cases
        {
            3,
            { { CountLayers, 1 } },
            { 0 },
        },
        {
            3,
            { { 2, 3 }, { CountLayers, 1 } },
            { 0 },
        },
        {
            3,
            { { 2, 3 }, { CountLayers, 2 }, { CountLayers, 2 } },
            { 1, 1 },
        },

        // example from description
        { 5, {
                 { 2, 4 },
                 { CountLayers, 3 },
                 { 3, 5 },
                 { CountLayers, 4 },
                 { CountLayers, 2 },
                 { CountLayers, 5 },
             },
            { 1, 2, 1, 1 } },
    }));
    CAPTURE(plankCount, workPlan);
    REQUIRE(countLayersOfPaintFor(plankCount, workPlan) == expectedResult);
}

https://godbolt.org/z/13oMr3P6j

3

Bardziej na temat:

Testując kod na stronie, z której wziąłem to zadanie na 40 testów 7 kończy się przekroczeniem limitu czasu (1 s). Zastanawiam się jak mogę przyspieszyć dodawanie warstw do desek (bo jedynie tu widze problem).

Zacznijmy od głupiego problemu:

Wiele zadań tego typu ma wadę, że ważna częścią jest optymalizacja operacji wejścia wyjścia.
Zasady są proste:

  1. Na początku, wyłaczyć synchonizację pmidzy strumieniami z C i C++ oraz pmiędzy strumieniem wejscia i wyjścia.
void SetupIO()
{
    std::sync_with_stdio(false);
    std::cin.tie(nullptr);
}

int main()
{
    SetupIO();
  1. Nie używać std::endl zamiast niego użyć '\n'

Problem zasadniczy:

Twój algorytm jest prostą implementacją brutal force. Dla dużego zakresu danych, twój kod robi za dużo zbędnych rzeczy.
Np dla danych:

100000 5
1 1 99994
1 2 99996
1 3 99998
1 4 100000
2 1

Twój kod robi od groma zbędnych rzeczy.

Twój kod ma asymptotyczna złożonośc optymistyczna: O(n * m) a bez problemu można uzyskać O(m)

99% zadań tego typu jest taka, że prosty algorytm, łatwy w napisaniu nie mieści się w limicie czasowym dla danych przy granicy zakresu danych wejściowych.
Celem takich zadań, jest zmuszenie kogoś do znalezienia lepszego bardziej optymalnego rozwiązania

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.