Ordinea învățării conținuturilor (roadmap)
Autor: Ștefan-Cosmin Dăscălescu
Introducere#
În ultimii ani, au apărut foarte multe resurse care permit învățarea algoritmilor și structurilor de date într-un mod complet fără prea multe probleme. Totuși, o mare problemă care încă există în prezent este lipsa unei structuri clare care să permită înțelegerea acestor noțiuni, adaptată la cerințele sistemului educațional din România și a diverselor niveluri, mai ales când vine vorba de olimpiadă și de concursurile de informatică.
Chiar dacă programele școlare, fie că e vorba de programele cadru sau programele claselor de la olimpiadă sunt un pas important făcut în special în ultimii ani, totuși încă nu există o ordine clară în care aceste noțiuni sunt discutate, ci doar o listă a noțiunilor care trebuie parcurse la un anumit nivel, fără a ține cont de dificultatea relativă a acestora.
În acest articol, vom prezenta ordinea pe care o propunem pentru învățarea acestor noțiuni, acesta fiind un roadmap pe care îl recomandăm tuturor pasionaților de algoritmi și structuri de date, și nu numai.
Cu alte cuvinte, vom putea spune că sunteți la \(10\) capitole distanță de a putea ajunge la olimpiada internațională de informatică. Totuși, aceste capitole necesită foarte multă muncă, timp și efort pentru a fi studiate și înțelese temeinic.
Clarificări și precizări#
În arhivă, avem secțiunile Ușor, Mediu, Dificil și Avansat care au drept scop crearea unei împărțiri aproximative a conținuturilor pe niveluri de dificultate. De asemenea, fiecare articol va avea la început o listă de articole pe care le recomandăm să le citiți înainte să citiți articolul curent, pentru a înțelege mai bine conținutul (de exemplu, pentru a citi articolul despre aflarea cifrelor unui număr, trebuie să știți să lucrați cu operatori și expresii).
În cele ce urmează, vom prezenta o ordine în care recomandăm învățarea noțiunilor și parcurgerea arhivei, de la cele mai ușoare până la cele mai dificile dintre cele prezente aici și nu numai, ordinea fiind una într-o ordine relativ crescătoare a dificultății.
Capitolul 0 - Articole generale#
Chiar dacă acesta este capitolul \(0\), se recomandă întoarcerea la el de fiecare dată când concurați sau vreți să aflați mai multe despre ce vă așteaptă.
Informații generale și programa olimpiadelor#
- Informații despre olimpiada de informatică
- Listă de concursuri relevante
- Programa pentru gimnaziu
- Programa pentru liceu
Strategie, sfaturi utile pentru olimpiade și concursuri#
- Cum te pregătești pentru olimpiadă?
- Abordarea concursurilor de pe Codeforces/AtCoder
- Cum ajungi tot mai bun la concursuri?
- Cum abordezi proba de concurs la olimpiadă?
- Cum ajungi să iei rezultate tot mai bune la olimpiadă?
- Cum gestionezi presiunea concursurilor?
Capitolul 1 - Noțiuni elementare de limbaj, algoritmi elementari#
Această secțiune își propune să vă ducă de la baze și să puteți ajunge să rezolvați probleme ușoare, precum și să vă familiarizați cu algoritmica, limbajul C++ și în general, tehnici de bază de rezolvare a problemelor.
Secțiune specială
Aceste noțiuni de bază sunt discutate și aici, dar vom relua discuția și mai jos.
Cum înveți materia?#
- De unde începi?
- Cum ajungi să stăpânești materia de la clasă?
- Cum să te pregătești pentru bacalaureat și admitere?
Fundamentele limbajului C++#
- Instalarea primului editor/IDE C++
- Primul program în C++
- Variabile și tipuri de date simple
- Operatori și expresii. Cunoștințe matematice de bază
- Citirea și afișarea datelor
- Coding Style
Structuri alternative și repetitive#
- Structura alternativă
- Structura repetitivă
- Prelucrarea cifrelor unui număr
- Maxime și minime
- Generarea șirurilor de numere
Algoritmi elementari#
Capitolul 2 - Tablouri, tehnici introductive#
Aici trecem la niște conținuturi mai avansate, cunoașterea tablourilor și a unor metode de bază inspirate din aritmetică și algebră devine necesară pentru a putea trece la noțiuni mai specifice.
Lucrul cu tablouri#
Algoritmi și tehnici introductive#
- Complexități
- Simularea soluției
- Algoritmi de sortare - Doar algoritmii în \(O(n^2)\) și funcția std::sort
- Ciurul lui Eratostene
- Sume parțiale - Doar sumele parțiale
- Cum repari o soluție greșită? - sfaturile inițiale
Capitolul 3 - Sortare, căutare, tehnici mai avansate de limbaj#
Dacă ați ajuns aici, înseamnă că aveți o bază relativ solidă și puteți să învățați și alte metode care ajung să fie un fundament pentru multe concursuri de algoritmică. Fie că este vorba de algoritmi deprinși din cei pentru sortări și căutări sau chiar de noțiuni matematice mai avansate, aici sunt algoritmii pe care îi veți folosi în multe situații și drept pași mai mici pentru alte metode mai avansate.
Tehnici de limbaj#
Algoritmi și metode de rezolvare a problemelor#
Noțiuni de algebră#
- Principiul lui Dirichlet (principiul cutiei)
- Baze de numerație
- Indicatorul lui Euler
- Aritmetică modulară. Ridicare la putere în timp logaritmic
Capitolul 4 - Structuri de date liniare, fundamentele tehnicilor avansate#
În această secțiune vom începe să rafinăm lucrurile folosind structuri de date liniare, precum coada, stiva și deque-ul, dar și să introducem tehnici mai avansate, precum teoria grafurilor și programarea dinamică. Continuăm și parcurgerea noțiunilor matematice.
Elemente de implementare#
- Cum repari o soluție greșită? - generarea testelor
- Tehnica divide et impera
- Căutare completă. Tehnica Backtracking
- Algoritmi de sortare - Restul algoritmilor de sortare
- Numere mari
- Normalizarea datelor
Matematică#
Structuri de date#
Abordarea anumitor tipuri de probleme mai speciale#
Introducere în tehnici mai avansate#
- Introducere în teoria grafurilor
- Introducere în arbori. Diametrul unui arbore
- Introducere în programarea dinamică
Capitolul 5 - Programarea dinamică (I), teoria grafurilor (I), combinatorică și geometrie#
Aici intrăm încet-încet în complexitatea a două dintre cele mai importante tehnici din algoritmică, programarea dinamică și teoria grafurilor. De asemenea, combinatorica și geometria sunt și ele abordate, existând multe probleme care folosesc aceste tehnici.
Programarea dinamică#
- Problema rucsacului
- Subșir comun maximal
- Subșir crescător maximal
- Dinamică pe stări exponențiale (bitmask DP)
Teoria grafurilor#
- Sortare topologică
- Cicluri în grafuri. Grafuri funcționale
- Păduri de mulțimi disjuncte (DSU)
- Arbore parțial de cost minim (Kruskal, Prim, Boruvka)
- Algoritmi pentru drumuri minime (Dijkstra, Bellman-Ford, Floyd-Warshall)
- Tehnica celor 2 DFS-uri (rerooting)
Matematică#
Alte noțiuni#
Capitolul 6 - Structuri de date, lucrul cu arbori, probleme speciale#
Aici începem să lucrăm cu structurile de date care ne ajută să răspundem la întrebări și să performăm actualizări într-un timp rapid. De asemenea, lucrăm în moduri mai detaliate cu arbori și grafuri, dar și cu alte tipuri de probleme pe care le întâlniți la concursuri.
Structuri de date#
- Descompuneri în bucăți de radical (Square Root Decomposition)
- Arbori de intervale
- Arbori indexați binar
- Range Minimum Query (RMQ)
- Trie
- Dinamici pe structuri de date
- Baleiere (sweep line)
Lucrul cu arbori#
- Binary lifting. Lowest common ancestor (LCA)
- Euler Tour
- Dinamici pe arbori
- Small to large
- Heavy Light Decomposition
- Centroid Decomposition
Abordarea anumitor tipuri de probleme mai speciale#
Alte tehnici#
Capitolul 7 - Programare dinamică (II), Teoria grafurilor (II), Matematică#
Continuăm munca de la capitolul 5 cu adaptări mai avansate ale metodelor menționate acolo, experiența devenind tot mai importantă.
Programarea dinamică#
- Programare dinamică pe intervale (range DP)
- Programare dinamică pe cifre (digit DP)
- Programare dinamică pe grafuri
- Programare dinamică pe permutări
Teoria grafurilor#
Algebră#
- Introducere în probabilități
- Introducere în algebră liniară
- Ridicare la putere a unei matrici
- Algoritmul lui Gauss
Geometrie#
Capitolul 8 - Matematică avansată, algoritmi pe stringuri#
Aici intrăm deja în algoritmi și tehnici de o complexitate foarte ridicată, aceștia trebuie să fie știuți de cei care vor să ajungă la cel mai înalt nivel.
Matematică avansată#
Algoritmi pe stringuri#
- Rotație lexicografică minimă
- Hashing
- Knuth-Morris-Pratt (KMP)
- Z Function
- Algoritmul lui Manacher
- Suffix array/tree
Capitolul 9 - Structuri de date avansate, DP Optimizations, Algoritmi avansați pe grafuri, matematică#
Acest capitol este unul open-ended, putând fi denumit mai informal drept restul algoritmicii, deoarece aici, pe lângă conținuturile menționate, orice alt conținut pe care îl considerați că trebuie abordat, îl puteți aborda.
Pe lângă aceste conținuturi menționate aici, orice altceva ce vreți să învătați ar trebui învățat după ce vă asigurați că stăpâniți algoritmii menționați anterior. În mod evident, există anumite excepții, dar dacă ați ajuns la acest nivel, probabil că știți și voi cum să ajustați anumite lucruri în funcție de ce observați în studiul vostru individual.
Structuri de date#
Optimizări specifice programării dinamice#
Algoritmică avansată pe grafuri#
Matematică#
- Run-length encoding
- Teorema chineză a resturilor (CRT)
- Recurențe liniare
- Funcții generatoare
- FFT, NTT
- Matematică avansată
Concluzii#
Stăpânirea noțiunilor într-o ordine clară care să permită înțelegerea tuturor capitolelor cu ușurință este esențială pentru orice competitor care vrea să ajungă cât mai bun, iar odată cu această resursă, avem prima structură completă în limba română a unui asemenea roadmap care face învățarea algoritmilor și structurilor de date mult mai ușoară chiar și dacă nu aveți un profesor îndrumător sau altcineva care să vă ajute să aveți o ordine logică în învățare.
Ca întotdeauna, vă stăm la dispoziție pe serverul nostru în cazul în care aveți sugestii de orice fel și/sau considerați că anumite noțiuni merită ajustate.