#include // Ošklivý, ale praktický trik (funguje jen v GCC) using namespace std; // Intervalový strom a uložené líné operace vector > max_int, lazy; // Funkce, která upraví hodnotu v daném poschodí a pozici na hodnotu v lazy inline void lazyupdate(int floor, int position) { max_int [floor] [position] = lazy [floor] [position]; // Když nejsme v nejspodnějším poschodí, posuneme línou operaci dolů if (floor < max_int.size() - 1) { lazy [floor + 1] [position * 2] = lazy [floor] [position]; lazy [floor + 1] [position * 2 + 1] = lazy [floor] [position]; } // Operaci jsme provedli, můžeme ji smazat lazy [floor] [position] = 0; } // Vrátí největší prvek v úseku [begin, end) int fetch(int floor, int position, int begin, int end) { // Pokud je třeba, provedeme línou operaci if (lazy [floor] [position]) lazyupdate(floor, position); // Délka intervalu pokrytého vrcholem a jeho [začátek, konec) int intlen = 1<<(max_int.size() - 1 - floor), intbegin = intlen * position, intend = intbegin + intlen; if (intbegin >= begin && intend <= end) // Celý uvnitř dotazovaného intervalu return max_int [floor] [position]; if (intbegin < end && intend > begin) // Překrývá se s dotazovaným intervalem return max( fetch(floor + 1, position * 2, begin, end), fetch(floor + 1, position * 2 + 1, begin, end)); return 0; } // Upraví hodnotu na úseku [begin, end) na v int update(int floor, int position, int begin, int end, int v) { // Zde by se nacházelo provedení líné operace. Protože ale upravujeme // vždy přesně ten interval, na který se předtím ptáme, není to třeba. int intlen = 1<<(max_int.size() - 1 - floor), intbegin = intlen * position, intend = intbegin + intlen; if (intbegin >= begin && intend <= end) { // Jenom si poznamenáme línou operaci. lazy [floor] [position] = v; return v; } if (intbegin < end && intend > begin) { // Update na dětech max_int [floor] [position] = max ( update(floor + 1, position * 2, begin, end, v), update(floor + 1, position * 2 + 1, begin, end, v)); } return max_int [floor] [position]; } int main () { int s, n; scanf("%d %d", &s, &n); vector helper(1, 0); // Vytvoříme a naplníme vektory pro intervalový strom. for (int i = 0; (1 << i) < s; i++) { max_int.push_back(helper); lazy.push_back(helper); helper.resize(1<<(i+1), 0); } max_int.push_back(helper); lazy.push_back(helper); int w, h, l; for (int i = 0; i < n; i++) { scanf("%d %d %d", &w, &h, &l); // V tomto řešení si pamatujeme nejvyšší obsazené políčko + 1. int res = fetch(0, 0, l, l+w); update(0, 0, l, l+w, res+h); printf("%d\n", res); } return 0; }