This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |