#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;
auto parentIndex = index;
while (parentIndex /= 2) {
auto sonLeftIndex = parentIndex * 2;
auto sonRightIndex = sonLeftIndex + 1;
tree[parentIndex] = (tree[sonLeftIndex] * tree[sonRightIndex]) % modulo;
}
}
uint32_t range_prod(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
) {
SegmentTree tree(largest.size(), modulo);
size_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 &[_, 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);
auto combinationsForKind = tree.range_prod(0, left - 1) +
(count[kind] % modulo) * tree.range_prod(0, kindIndex[kind]);
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);
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
1 ms |
308 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
120 ms |
12816 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
2 ms |
340 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
51 ms |
5564 KB |
Output is correct |
2 |
Correct |
65 ms |
6780 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
2 ms |
416 KB |
Output is correct |
2 |
Correct |
2 ms |
532 KB |
Output is correct |
3 |
Correct |
2 ms |
468 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
83 ms |
8780 KB |
Output is correct |
2 |
Incorrect |
159 ms |
13536 KB |
Output isn't correct |
3 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
142 ms |
13108 KB |
Output is correct |
2 |
Correct |
138 ms |
14500 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
84 ms |
9060 KB |
Output is correct |
2 |
Correct |
145 ms |
14192 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
136 ms |
13500 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
164 ms |
15792 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
153 ms |
14372 KB |
Output is correct |
2 |
Correct |
200 ms |
21520 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
272 ms |
23252 KB |
Output is correct |
2 |
Correct |
216 ms |
19292 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
249 ms |
22036 KB |
Output is correct |
2 |
Correct |
249 ms |
21428 KB |
Output is correct |
3 |
Correct |
285 ms |
27684 KB |
Output is correct |
4 |
Correct |
238 ms |
21452 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
367 ms |
28056 KB |
Output is correct |
2 |
Correct |
429 ms |
50584 KB |
Output is correct |
3 |
Correct |
462 ms |
51556 KB |
Output is correct |
4 |
Correct |
500 ms |
43640 KB |
Output is correct |