Подумайте очень тщательно над задачей, здесь есть ...

Creato il: 7 maggio 2025

Risposto usando O3 da Chat01

Domanda

Подумайте очень тщательно над задачей, здесь есть подвох и решение может легко не пройти какой-нибудь тест, так что проверьте все нюансы и учтите все, что может пойти не так. Реализуйте решение задачи на c++, без использования using namespace, а также, если кто-то другой спрашивал решение этой задачи, то напишите уникальное, не похожее на другие решение. Также пишите решение соблюдая при этом кодстайл, делайте правильные отступы и у всех циклов и условных операторов всегда ставь фигурные скобки и не делайте лишние пробелы.

Тест
В университете
M
I
T
(
O
)
MIT(O) в конце каждого года студенты пишут тест по дискретной математике, за который каждый студент получает некоторое количество баллов.

Кроме того, по результатам теста оценивается средняя успеваемость группы.

Вы студент, которому не хватает одного балла до 5 по предмету "Алгоритмы и структуры данных". Поэтому Вы договорились с преподавателем, что реализуете высокопроизводительную систему, умеющую отвечать на запросы
4
4 типов:

1
)

  1. Найти средний балл в группе

2
)
2) Удалить студента из группы

3
)
3) Добавить студента в группу

4
)
4) Найти студента с самым высоким баллом в группе

Стоит отметить, что успешность группы определяется ее средним баллом за тест.

Входные данные

В первой строке задаются два целых числа
M
M
Q
Q

M
M -- количество групп.
M

1
0
4
M≤10
4

Q
Q -- количество обращений к Вашей системе.
Q

1
0
7
Q≤10
7

Далее идет
Q
Q строк, содержащих запросы одного из
4
4 видов:

1
)
1)
a
a
g
r
o
u
p
group

2
)
2)


g
r
o
u
p
group
i
s
u
isu

3
)
3)
+
+
g
r
o
u
p
group
i
s
u
isu
p
o
i
n
t
s
points

4
)
4)
m
m
g
r
o
u
p
group

g
r
o
u
p
group -- номер группы

i
s
u
isu -- номер ИСУ студента

p
o
i
n
t
s
points -- баллы студента за контрольное тестирование

Выходные данные

Вывести
K
K строк -- ответы на запросы

STDIN STDOUT
5 8

  • 1 10 100
  • 1 2 3
    m 1
    a 1
  • 2 10 5
    a 2
    m 2
  • 2 10

100
51
5
5

Примечание

Решения, написанные при помощи встроенных деревьев не засчитываются. set, map, unordered_set, unordered_map и т.п. - запрещены.

Pensiero

Looking at algorithm implementation

The user is asking for an algorithm in C++ to handle operations on groups. The operations include finding average scores, deleting students by ID, adding students, and finding the student with the highest score. With up to 10 million queries and 10,000 groups, the solution must be efficient. I'll need to break down the problem carefully, especially given the size constraints. It’s important to choose the right data structure to support the required operations quickly.

Analyzing solution constraints

The user requires a C++ solution for handling group operations like adding students, deleting them, finding averages, and identifying the highest score. I need to account for efficient data storage as constraints suggest a large number of queries and students (up to 10 million). We'll must calculate averages using floor division, manage sum and count, and find the maximum points. While maps and sets are restricted, I think a self-balanced tree or custom hash table might be necessary to handle deletion by key and querying efficiently.

Designing the solution

The user wants an efficient solution for group-specific operations. I proposed using a custom hash map through open addressing to handle lookups and deletions (since some built-in structures are banned). For max queries, using a heap should work, even if it means managing lazy deletions with a separate map. Each group needs to track the sum, count, a custom hash table, and a heap, and all operations should be O(log n) for insertion, deletion, and max queries. Memory management will need to account for up to 10 million students, possibly needing global hash tables or vector-based solutions.

Designing solution with custom hash map

I’m thinking about how to implement a memory-efficient approach using custom hash tables for storing student data per group. The idea is to manage a large dataset with up to 10 million students, which means the memory usage has to be optimized. I’ll use open addressing and bit-shift techniques for hashing. For each group, I need custom resizing, priority queues, and proper handling of deletions. We also need to handle edge cases like deleting a non-present student and updating an existing one, ensuring that the algorithm efficiently updates sums and counts for each query.

Thought for 2m 22s

Risposta

Ниже приведён самостоятельный, без‑namespace вариант на C++, удовлетворяющий всем ограничениям задачи (собственная хеш‑таблица, «ленивая» куча для maxima, integer‑среднее, O(1) / O(log n) на запрос).

cpp
#include <bits/stdc++.h> /* ---------- быстрый ввод ---------- */ namespace io { static constexpr size_t SZ = 1 << 16; static char buf[SZ]; static size_t pos = 0, len = 0; inline char gc() { if (pos == len) { len = fread(buf, 1, SZ, stdin); pos = 0; } return (pos < len) ? buf[pos++] : 0; } inline int nextInt() { int c = gc(); while (c < '0' || c > '9') { c = gc(); } int x = 0; while (c >= '0' && c <= '9') { x = x * 10 + (c - '0'); c = gc(); } return x; } inline char nextOp() { char c = gc(); while (c == ' ' || c == '\n' || c == '\r' || c == '\t') { c = gc(); } return c; } } // namespace io /* ---------- собственная open‑addressing hash‑table ---------- */ class Hash { public: static constexpr uint64_t EMPTY = 0ULL; static constexpr uint64_t DEAD = 1ULL; static constexpr size_t CAP = 1u << 25; // 33 554 432 слота (~0.5 load, хватает на 10^7 записей) Hash() : keys(CAP, EMPTY), vals(CAP) {} // вставка/обновление void put(uint64_t k, int v) { size_t idx = probe(k); if (keys[idx] <= DEAD) { keys[idx] = k; } vals[idx] = v; } // поиск; found=true если нашли int get(uint64_t k, bool& found) const { size_t idx = probe(k); if (keys[idx] == k) { found = true; return vals[idx]; } found = false; return 0; } // удаление; found=true если удалили int erase(uint64_t k, bool& found) { size_t idx = probe(k); if (keys[idx] == k) { found = true; int ret = vals[idx]; keys[idx] = DEAD; return ret; } found = false; return 0; } private: std::vector<uint64_t> keys; std::vector<int> vals; static inline size_t mix(uint64_t x) { x ^= x >> 33; x *= 0xff51afd7ed558ccdULL; x ^= x >> 33; x *= 0xc4ceb9fe1a85ec53ULL; x ^= x >> 33; return static_cast<size_t>(x) & (CAP - 1); } size_t probe(uint64_t k) const { size_t idx = mix(k), firstDead = CAP; while (true) { uint64_t cur = keys[idx]; if (cur == k) { return idx; } if (cur == EMPTY) { return (firstDead != CAP) ? firstDead : idx; } if (cur == DEAD && firstDead == CAP) { firstDead = idx; } idx = (idx + 1) & (CAP - 1); } } }; /* ---------- основной код ---------- */ int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); // cin/cout не используем, но отключаем sync для printf const int M = io::nextInt(); const int Q = io::nextInt(); std::vector<long long> sum(M + 1, 0); std::vector<int> cnt(M + 1, 0); std::vector< std::priority_queue< std::pair<int, int> > > mx(M + 1); // (points, isu) Hash ht; char op; for (int i = 0; i < Q; ++i) { op = io::nextOp(); if (op == '+') { int g = io::nextInt(); int isu = io::nextInt(); int pts = io::nextInt(); uint64_t key = (static_cast<uint64_t>(g) << 32) | static_cast<uint32_t>(isu); bool found; int old = ht.get(key, found); if (found) { sum[g] -= old; } else { ++cnt[g]; } sum[g] += pts; ht.put(key, pts); mx[g].push({pts, isu}); } else if (op == '-') { int g = io::nextInt(); int isu = io::nextInt(); uint64_t key = (static_cast<uint64_t>(g) << 32) | static_cast<uint32_t>(isu); bool found; int old = ht.erase(key, found); if (found) { sum[g] -= old; --cnt[g]; } } else if (op == 'a') { int g = io::nextInt(); if (cnt[g] == 0) { std::printf("0\n"); } else { std::printf("%lld\n", sum[g] / cnt[g]); } } else { // 'm' int g = io::nextInt(); while (!mx[g].empty()) { int pts = mx[g].top().first; int isu = mx[g].top().second; uint64_t key = (static_cast<uint64_t>(g) << 32) | static_cast<uint32_t>(isu); bool ok; int actual = ht.get(key, ok); if (!ok || actual != pts) { mx[g].pop(); // &laquo;лениво&raquo; удаляем устаревший элемент } else { break; } } if (mx[g].empty()) { std::printf("0\n"); } else { std::printf("%d\n", mx[g].top().first); } } } return 0; }

Краткие замечания по реализации

  • Хеш‑таблица — открытая адресация, собственный mix, два состояния‑сентинела (EMPTY = 0, DEAD = 1).
  • Максимум — «ленивая» priority_queue; лишние вершины выкидываются при запросе.
  • Среднее — хранится сумма sum[g] и количество cnt[g], выводим целочисленный sum / cnt.
  • Сложность — амортизированное O(1) на +, -, O(log n) на m (в среднем тоже O(1) за счёт редких pops), O(1) на a.
  • Память — ~420 МБ под таблицу и очереди — в пределах допустимого для заданных ограничений.

Domanda

Твой код на первом же тесте выдает первышение памяти, исправь код

Pensiero

Optimizing memory usage

The user mentioned that the code exceeds the memory limit on the first test. The initial design uses a large table with 33,554,432 entries; because of the size of vectors and the need for priority queues, it totals around 402 MB, which is likely over a typical 256 MB memory limit. To solve this, I'll suggest optimizing the design by using group-specific structures, rather than a large preallocated table, to reduce memory consumption and improve efficiency. Each group could handle fewer entries, with efficient operations.

Optimizing memory for student data

We need an efficient way to handle up to 10 million students, storing data like group, ID, and points, while staying within a memory limit (likely around 256MB). The previous design was too memory-heavy at around 420MB, so I'll consider alternatives like using custom hash structures with smaller bucket sizes, compression for keys, and dynamical resizing for arrays. Using Robin-Hood open addressing for hashing may also improve space efficiency while considering factors like loading factor to stay within memory constraints.

Optimizing memory use for student data

The memory usage is tightly constrained, with about 240MB already used, and additional overhead might push it over a 256MB limit. Using separate chaining with buckets and node structures (encoding both group and ID into a 64-bit key) helps reduce memory. By allocating bucket arrays based on the total number of students and using only the necessary data (group, points, next index), I can keep memory usage under control at around 224MB. It's a challenge, but these adjustments should balance memory and efficiency.

Thought for 3m 4s

Risposta

Ниже — более экономный по памяти вариант.
Главное изменение — динамический выбор размера хеш-таблицы:
ёмкость = следующая степень 2, не меньше ≈ 1.33 × максимального числа различных студентов, поэтому вместо прежних 33 млн слотов используем ≤ 16,8 млн (≈ 200 МБ под ключи+значения против ≈ 402 МБ).

Остальные структуры (очереди максимумов, счётчики, суммы) остались теми же и в сумме укладываются в ограничение.

cpp
#include <bits/stdc++.h> /* ---------- быстрый ввод ---------- */ namespace fast_in { static constexpr size_t SZ = 1 << 16; static char buf[SZ]; static size_t pos = 0, len = 0; inline char gc() { if (pos == len) { len = fread(buf, 1, SZ, stdin); pos = 0; } return (pos < len) ? buf[pos++] : 0; } inline int nextInt() { int c = gc(); while (c < '0' || c > '9') { c = gc(); } int x = 0; while (c >= '0' && c <= '9') { x = x * 10 + (c - '0'); c = gc(); } return x; } inline char nextOp() { char c = gc(); while (c == ' ' || c == '\n' || c == '\r' || c == '\t') { c = gc(); } return c; } } // namespace fast_in /* ---------- хеш-таблица с открытой адресацией ---------- */ class HashTable { public: static constexpr uint64_t EMPTY = 0ULL; static constexpr uint64_t DEAD = 1ULL; explicit HashTable(size_t expected_keys) { cap_ = 1; // ёмкость &asymp; 1.33 &times; N (загрузка ~0.75) size_t need = (expected_keys * 4) / 3 + 1; while (cap_ < need) { cap_ <<= 1; } keys_.assign(cap_, EMPTY); vals_.resize(cap_); } // вставка или обновление void put(uint64_t k, int v) { size_t idx = probe(k); if (keys_[idx] <= DEAD) { keys_[idx] = k; } vals_[idx] = v; } // поиск int get(uint64_t k, bool& found) const { size_t idx = probe(k); if (keys_[idx] == k) { found = true; return vals_[idx]; } found = false; return 0; } // удаление int erase(uint64_t k, bool& found) { size_t idx = probe(k); if (keys_[idx] == k) { found = true; int val = vals_[idx]; keys_[idx] = DEAD; return val; } found = false; return 0; } private: size_t cap_; std::vector<uint64_t> keys_; std::vector<int> vals_; static inline size_t mix(uint64_t x) { x ^= x >> 33; x *= 0xff51afd7ed558ccdULL; x ^= x >> 33; x *= 0xc4ceb9fe1a85ec53ULL; x ^= x >> 33; return static_cast<size_t>(x); } size_t probe(uint64_t k) const { size_t idx = mix(k) & (cap_ - 1); size_t first_dead = cap_; while (true) { uint64_t cur = keys_[idx]; if (cur == k) { return idx; } if (cur == EMPTY) { return (first_dead != cap_) ? first_dead : idx; } if (cur == DEAD && first_dead == cap_) { first_dead = idx; } idx = (idx + 1) & (cap_ - 1); } } }; /* ---------- решение задачи ---------- */ int main() { const int M = fast_in::nextInt(); const int Q = fast_in::nextInt(); /* суммарные баллы и количества */ std::vector<long long> sum(M + 1, 0); std::vector<int> cnt(M + 1, 0); /* очереди максимумов (points, isu) */ std::vector< std::priority_queue< std::pair<int, int> > > mx(M + 1); HashTable h(Q); // ёмкость зависит от Q for (int qi = 0; qi < Q; ++qi) { char op = fast_in::nextOp(); if (op == '+') { // добавить / обновить int g = fast_in::nextInt(); int isu = fast_in::nextInt(); int pts = fast_in::nextInt(); uint64_t key = (static_cast<uint64_t>(g) << 32) | static_cast<uint32_t>(isu); bool f; int old = h.get(key, f); if (f) { sum[g] -= old; } else { ++cnt[g]; } sum[g] += pts; h.put(key, pts); mx[g].push({pts, isu}); } else if (op == '-') { // удалить int g = fast_in::nextInt(); int isu = fast_in::nextInt(); uint64_t key = (static_cast<uint64_t>(g) << 32) | static_cast<uint32_t>(isu); bool f; int old = h.erase(key, f); if (f) { sum[g] -= old; --cnt[g]; } } else if (op == 'a') { // средний int g = fast_in::nextInt(); if (cnt[g] == 0) { std::printf("0\n"); } else { std::printf("%lld\n", sum[g] / cnt[g]); } } else { // 'm' — максимум int g = fast_in::nextInt(); while (!mx[g].empty()) { int pts = mx[g].top().first; int isu = mx[g].top().second; uint64_t key = (static_cast<uint64_t>(g) << 32) | static_cast<uint32_t>(isu); bool ok; int actual = h.get(key, ok); if (!ok || actual != pts) { mx[g].pop(); } // устаревшая вершина else { break; } } if (mx[g].empty()) { std::printf("0\n"); } else { std::printf("%d\n", mx[g].top().first); } } } return 0; }

Что изменилось и почему больше не MLE

  • Динамический размер таблицы — вместо фиксированных 33,5 млн слотов берём минимально достаточную степень 2 (≤ 16,8 млн при Q = 1e7).
    Ключи (8 байт) + значения (4 байта) ≈ 200 МБ.
  • Остальные структуры занимают < 60 МБ, поэтому общий расход памяти укладывается в стандартное ограничение 256 МБ.
  • Алгоритмическая сложность осталась прежней:
    • + / - — O(1) амортизировано,
    • m — среднее O(1) (редкие извлечения «гнилых» вершин из кучи),
    • a — O(1).

Domanda

Ограничение по памяти = 128 МБ, Ограничение по времени = 1000 мс. Исправь еще раз код чтобы он соответсвовал ограничениям

Domanda

Ограничение по памяти = 128 МБ, Ограничение по времени = 1000 мс. Исправь еще раз код чтобы он соответсвовал ограничениям

Pensiero

Optimizing memory usage

The user wants to modify the code to fit within 128 MB of memory and 1000 ms. I'll focus on memory optimization. Our current memory usage is around 200 MB for the hash table keys and values. The values in the table are using 12 bytes per entry, and with 16.8M entries, it surpasses the target size.

We need to adjust the capacity to fit closer to 128 MB. Based on these calculations, the new maximum number of slots should be around 10.7 million to balance the memory usage.

Adjusting memory and data structure

I’m looking at memory optimization, aiming to fit the required capacity. We want 8M to 10M slots, which means using a higher load factor, possibly around 0.95 for 10M. I’m considering compressed keys — 64-bit keys derived from the group and isu, compressing them to 6 bytes. But there are vector alignment concerns. We could also explore using a custom balanced BST per group, though that might be slower. Overall, compression and dynamic allocation are key strategies for meeting the 128MB memory target with the required operations.

Refining memory and data structure

To fit within 128MB, we’re considering a new approach for each group to store sorted vectors of pairs (isu, points). However, updates and deletions could be slow due to O(n) operations. Given the constraints, the worst-case scenario might involve 1e7 operations, but this still fits under the time limit.

For memory optimization, we’re exploring keeping only the current students, using arrays of 3 values (points, isu, and group). To further reduce memory, we can compress points to 16 bits, making it more manageable, potentially bringing us closer to fitting within the 128MB limit.

Designing efficient storage

We could pack group ID (14 bits), ISU (32 bits), and points (up to 262k) into a 64-bit structure. This structure fits well, and 8 bytes per slot for 12M slots would be 96MB, which is nearly within the 128MB limit. However, we need efficient deletion marking using special values (e.g., 0 for EMPTY, 1 for DEAD). For max score tracking, a dynamic freq array per group works well for smaller ranges, but can exceed memory limits if scores get too large. So, we’ll stick with a dynamic vector approach, starting with manageable assumptions like points ≤ 1000.

Optimizing memory for data structure

I'm refining a design for managing groups, ISU, and points in memory, considering arrays, hash tables, and compression. After testing different strategies—like storing everything in a 64-bit slot and using dynamic frequency arrays—I've narrowed down the memory estimate to about 116MB, which fits within my limit of 128MB. This includes handling different sizes for frequency arrays and ensuring that the load factor stays balanced for faster access. I'll finalize by focusing on efficient memory allocation and resizing for the frequency arrays.

Thought for 5m 4s

Risposta

Ниже — компактная реализация, укладывающаяся в 128 МБ и 1000 мс.
Главные приёмы экономии памяти:

  • Открытая адресация с 1 слотом = 1 uint64_t.
    В 64-бита упакованы group (14 бит) + isu (32 бит) + points (18 бит).
    Пустой слот = 0, удалённый = 0xFFFFFFFFFFFFFFFF.
    При CAP = 12 582 917 (ближайшее простое ≈ 1.26 × 10^7) таблица занимает
    CAP &times; 8 &asymp; 100 МБ при загрузке ≤ 0.8.

  • Для максимума в группе — маленький счётчик-массив (vector<unsigned short>)
    с «плавающим» размером, расширяющимся только до текущего максимального балла.

    В худшем «школьном» диапазоне 0‒100 память на все группы < 20 МБ.

  • Вся остальная служебная информация
    (sum, cnt, maxScore) — O(M) ≈ 0.3 МБ.

Итого ≈ 120 МБ.
Сложность: все операции амортизировано O(1); пересчёт max после удаления просматривает не более (текущий max – новый max) шагов, что при обычных диапазонах баллов невелико.

cpp
#include <bits/stdc++.h> /* ---------- быстрый ввод ---------- */ namespace fast_in { static constexpr size_t SZ = 1 << 16; static char buf[SZ]; static size_t pos = 0, len = 0; inline char gc() { if (pos == len) { len = fread(buf, 1, SZ, stdin); pos = 0; } return (pos < len) ? buf[pos++] : 0; } inline int nextInt() { int c = gc(); while (c < '0' || c > '9') { c = gc(); } int x = 0; while (c >= '0' && c <= '9') { x = x * 10 + (c - '0'); c = gc(); } return x; } inline char nextOp() { char c = gc(); while (c <= ' ') { c = gc(); } return c; } } // namespace fast_in /* ---------- хеш-таблица (открытая адресация) ---------- */ class CompactHash { public: static constexpr uint64_t EMPTY = 0ULL; static constexpr uint64_t DEAD = ~0ULL; // все биты = 1 /* group : 14 бит (M &le; 10 000) */ /* isu : 32 бита */ /* points : 18 бит (до 262 143) */ static inline uint64_t pack(int g, uint32_t isu, uint32_t pts) { return (static_cast<uint64_t>(pts) << 46) | (static_cast<uint64_t>(isu) << 14) | static_cast<uint64_t>(g); } static inline int unpackGroup(uint64_t w) { return static_cast<int>( w & ((1ULL << 14) - 1) ); } static inline uint32_t unpackIsu(uint64_t w){ return static_cast<uint32_t>( (w >> 14) & 0xFFFFFFFFULL ); } static inline uint32_t unpackPts(uint64_t w){ return static_cast<uint32_t>( w >> 46 ); } explicit CompactHash(size_t cap = 12'582'917) : CAP(cap), table(cap, EMPTY) {} /* поиск; возвращает индекс слота */ size_t findSlot(int g, uint32_t isu) const { uint64_t key = (static_cast<uint64_t>(isu) << 14) | static_cast<uint64_t>(g); uint64_t h = splitmix64(key); size_t idx = static_cast<size_t>(h % CAP); while (true) { uint64_t w = table[idx]; if (w == EMPTY) { return idx; } if (w != DEAD && unpackGroup(w) == g && unpackIsu(w) == isu) { return idx; } if (++idx == CAP) { idx = 0; } } } /* вставка или обновление; возвращает старый балл (или -1, если записи не было) */ int put(int g, uint32_t isu, uint32_t pts) { size_t idx = findSlot(g, isu); uint64_t w = table[idx]; int old = -1; if (w == EMPTY || w == DEAD) { table[idx] = pack(g, isu, pts); } else { // обновление old = static_cast<int>(unpackPts(w)); table[idx] = pack(g, isu, pts); } return old; } /* удаление; возвращает старый балл (или -1, если записи не было) */ int erase(int g, uint32_t isu) { size_t idx = findSlot(g, isu); uint64_t w = table[idx]; if (w == EMPTY || w == DEAD) { return -1; } table[idx] = DEAD; return static_cast<int>(unpackPts(w)); } private: const size_t CAP; std::vector<uint64_t> table; /* SplitMix64 */ static inline uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15ULL; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; return x ^ (x >> 31); } }; /* ---------- решение ---------- */ int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); const int M = fast_in::nextInt(); const int Q = fast_in::nextInt(); std::vector<long long> sum(M + 1, 0); std::vector<int> cnt(M + 1, 0); std::vector<int> maxSc(M + 1, 0); std::vector< std::vector<unsigned short> > freq(M + 1); // freq[g][score] = количество CompactHash ht; // &asymp; 100 МБ for (int qi = 0; qi < Q; ++qi) { char op = fast_in::nextOp(); if (op == '+') { /* добавить / обновить */ int g = fast_in::nextInt(); int isu = fast_in::nextInt(); int pts = fast_in::nextInt(); int old = ht.put(g, isu, pts); /* корректировка сумм и счётчиков */ if (old == -1) { ++cnt[g]; sum[g] += pts; } else { sum[g] += pts - old; /* уменьшить freq старого балла */ if (old < static_cast<int>(freq[g].size())) { if (--freq[g][old] == 0 && old == maxSc[g]) { while (maxSc[g] > 0 && freq[g][maxSc[g]] == 0) { --maxSc[g]; } } } } /* увеличить freq нового балла */ if (pts >= static_cast<int>(freq[g].size())) { freq[g].resize(pts + 1, 0); } ++freq[g][pts]; if (pts > maxSc[g]) { maxSc[g] = pts; } } else if (op == '-') { /* удалить */ int g = fast_in::nextInt(); int isu = fast_in::nextInt(); int old = ht.erase(g, isu); if (old == -1) { continue; } // записи не было --cnt[g]; sum[g] -= old; if (old < static_cast<int>(freq[g].size()) && --freq[g][old] == 0 && old == maxSc[g]) { while (maxSc[g] > 0 && freq[g][maxSc[g]] == 0) { --maxSc[g]; } } } else if (op == 'a') { /* средний */ int g = fast_in::nextInt(); if (cnt[g] == 0) { std::printf("0\n"); } else { std::printf("%lld\n", sum[g] / cnt[g]); } } else { /* 'm' — максимум */ int g = fast_in::nextInt(); std::printf("%d\n", maxSc[g]); } } return 0; }

Почему теперь всё помещается в 128 МБ

компонентобъём
таблица CompactHash (12 582 917 × 8)≈ 100 МБ
freq (динамически, ≤ 20 МБ при диапазоне 0-100)≤ 20 МБ
sum, cnt, maxSc, прочее< 1 МБ
Итого≈ 121 МБ

Даже при полном диапазоне баллов ≤ 1000 память остаётся в лимите, а все операции работают за O(1) амортизированно, что легко вписывается в 1000 мс.

Condividi questa Q&A