Submission #763807

#TimeUsernameProblemLanguageResultExecution timeMemory
763807matheuzizFish (IOI08_fish)C++17
100 / 100
453 ms43344 KiB
#include <bits/stdc++.h> #include <cstdint> #include <cstdlib> #include <stdint.h> struct SegmentTree { std::vector<uint32_t> tree; uint32_t size, modulo; SegmentTree(uint32_t numElements, uint32_t mod) { size = numElements; modulo = mod; tree = std::vector<uint32_t>(2 * numElements, 1); } void update(uint32_t index, uint32_t value) { index += size; tree[index] = value % modulo; auto parentIndex = index; while (parentIndex /= 2) { auto sonLeftIndex = parentIndex * 2; auto sonRightIndex = sonLeftIndex + 1; tree[parentIndex] = (tree[sonLeftIndex] * tree[sonRightIndex]) % modulo; } } uint32_t rangeProd(uint32_t start, uint32_t end) { uint32_t product = 1; if (end > size) return product; start += size; end += size; // Traverse the range and accumulate the product while (start <= end) { if (start & 1) { product = (product * tree[start]) % modulo; start++; } if (!(end & 1)) { product = (product * tree[end]) % modulo; end--; } start /= 2; end /= 2; } return product; } }; uint32_t calc_combinations( const std::vector<std::pair<uint32_t, uint32_t>>& largest, const std::vector<std::pair<uint32_t, uint32_t>>& fishes, const std::vector<std::vector<uint32_t>>& lengthsByKind, const std::vector<uint32_t>& kindIndex, std::vector<uint32_t>& count, const uint32_t& modulo ) { /* largest: (2, 1) (5, 0) (8, 2) fishes: (2, 1) (2, 2) (4, 0) (5, 0) (8, 2) lengthsByKind: 0 -> 4, 5 1 -> 2 2 -> 2, 8 kindIndex: 0 -> 1 1 -> 0 2 -> 2 count: 0, 0, 0 */ SegmentTree tree(largest.size(), modulo); uint32_t fishIndex = 0; uint32_t answer = 0; for (const auto &[length, kind] : largest) { // Go through all fish that current can eat // But start from previous big fish's index while (fishIndex < fishes.size() && 2 * fishes[fishIndex].first <= length) { auto &[fLen, fKind] = fishes[fishIndex]; count[fKind]++; // How many fishes have been eaten by kind tree.update(kindIndex[fKind], count[fKind] + 1); fishIndex++; } // Search over larger fishes of other kinds for the greatest fish that cannot // catch more fish of the current kind. uint32_t left = kindIndex[kind] + 1, right = largest.size() - 1; while (left <= right) { uint32_t mid = (left + right) / 2, eatableCount = 0; for (auto small : lengthsByKind[kind]) { if (small > largest[mid].first / 2) break; eatableCount++; } if (eatableCount <= count[kind]) { left = mid + 1; } else { right = mid - 1; } } tree.update(kindIndex[kind], 1); uint32_t combinationsForKind; auto cnt = (count[kind] % modulo); auto c1 = tree.rangeProd(0, left - 1); if (cnt) { auto c2 = tree.rangeProd(0, kindIndex[kind]); combinationsForKind = c1 + cnt * c2; } else { combinationsForKind = c1; } answer = (answer + combinationsForKind) % modulo; tree.update(kindIndex[kind], count[kind] + 1); } return answer; } int main() { uint32_t fishCount, gemCount, modulo; if (scanf("%u\n%u\n%u", &fishCount, &gemCount, &modulo) != 3) { exit(EXIT_FAILURE); } std::vector<std::pair<uint32_t, uint32_t>> fishes(fishCount), largest(gemCount, {0, 0}); std::vector<std::vector<uint32_t>> lengthsByKind(gemCount); std::vector<uint32_t> kindIndex(gemCount), count(gemCount, 0); for (auto &[length, kind] : fishes) { if (scanf("%u %u", &length, &kind) != 2) { exit(EXIT_FAILURE); } kind--; largest[kind] = std::max(largest[kind], {length, kind}); } std::sort(fishes.begin(), fishes.end()); std::sort(largest.begin(), largest.end()); for (size_t i = 0; i < largest.size(); i++) { kindIndex[largest[i].second] = i; } for (const auto &[length, kind] : fishes) { lengthsByKind[kind].push_back(length); } uint32_t answer = calc_combinations( largest, fishes, lengthsByKind, kindIndex, count, modulo ); printf("%d\n", answer); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...