# |
Submission time |
Handle |
Problem |
Language |
Result |
Execution time |
Memory |
526657 |
2022-02-15T21:21:22 Z |
LFFB |
Growing Trees (BOI11_grow) |
C++14 |
|
1000 ms |
11312 KB |
#include <iostream>
#include <vector>
#include <algorithm>
#define debug(args...) //printf(args)
#define pair(x, y) std::make_pair(x, y)
const int MAX_N = 100000 + 10;
const int MAX_NODES = 4 * MAX_N;
struct Node {
bool leaf;
int height;
int first;
int last;
int lazySum;
Node() {
height = 0;
first = 0;
last = 0;
lazySum = 0;
leaf = true;
}
Node(int h) {
height = h;
first = height;
last = height;
lazySum = 0;
leaf = true;
}
Node (Node* left, Node* right) {
height = 0;
first = left->first;
last = right->last;
lazySum = 0;
leaf = false;
}
void propagate(Node* left, Node* right) {
if (left->leaf) {
left->height += lazySum;
left->first = left->height;
left->last = left->height;
} else {
left->lazySum += lazySum;
left->first += lazySum;
left->last += lazySum;
}
if (right->leaf) {
right->height += lazySum;
right->first = right->height;
right->last = right->height;
} else {
right->lazySum += lazySum;
right->first += lazySum;
right->last += lazySum;
}
lazySum = 0;
}
};
int n;
int queries;
int input[MAX_N];
namespace SegmentTree {
Node nodes[MAX_NODES];
int indexes[MAX_N];
// first call to namespace, builds the tree from input array
Node* build(int index = 0, int start = 0, int end = -1) {
if (end == -1) end = n - 1;
if (start == end) {
nodes[index] = Node(input[start]);
indexes[start] = index;
return &nodes[index];
}
int leftIndex = 2 * index + 1;
int rightIndex = leftIndex + 1;
int mid = (start + end) / 2;
Node* left = build(leftIndex, start, mid);
Node* right = build(rightIndex, mid + 1, end);
nodes[index] = Node(left, right);
indexes[start] = index;
return &nodes[index];
}
// returns the first index such that values[index] >= value
int lowerBound(int value, int index = 0, int start = 0, int end = -1) {
if (end == -1) end = n - 1;
if (start == end) {
if (value > nodes[index].height) return start + 1;
return start;
}
Node* current = &nodes[index];
int leftIndex = 2 * index + 1;
int rightIndex = leftIndex + 1;
int mid = (start + end) / 2;
Node* left = &nodes[leftIndex];
Node* right = &nodes[rightIndex];
current->propagate(left, right);
if (value <= left->last) {
return lowerBound(value, leftIndex, start, mid);
} else {
return lowerBound(value, rightIndex, mid + 1, end);
}
}
// returns the number of values inside the range [min, max] (inclusive)
int query(int min, int max) {
int lower = lowerBound(min);
int higher = lowerBound(max + 1);
return higher - lower;
}
// internal return only
// returns 1 if parent should increase the endpoint
std::pair<int, int> updateRange(int lower, int higher, int index = 0, int start = 0, int end = -1) {
if (end == -1) end = n - 1;
if (higher < lower) return pair(0, 0);
if (start > higher || lower > end) return pair(0, 0);
if (start == end) {
nodes[index].height++;
nodes[index].first++;
nodes[index].last++;
return pair(1, 1);
}
if (end <= start && end <= higher) {
nodes[index].first++;
nodes[index].last++;
nodes[index].lazySum++;
return pair(1, 1);
}
int leftIndex = 2 * index + 1;
int rightIndex = leftIndex + 1;
int mid = (start + end) / 2;
std::pair<int, int> leftUpdate = updateRange(lower, higher, leftIndex, start, mid);
std::pair<int, int> rightUpdate = updateRange(lower, higher, rightIndex, mid + 1, end);
if (leftUpdate.first == 1) {
nodes[index].first++;
}
if (rightUpdate.second == 1) {
nodes[index].last++;
}
return pair(leftUpdate.first, rightUpdate.second);
}
int getValue(int x, int index = 0, int start = 0, int end = -1) {
if (end == -1) end = n - 1;
if (start == end) return nodes[index].height;
int leftIndex = 2 * index + 1;
int rightIndex = leftIndex + 1;
int mid = (start + end) / 2;
nodes[index].propagate(&nodes[leftIndex], &nodes[rightIndex]);
if (x <= mid) return getValue(x, leftIndex, start, mid);
if (x > mid) return getValue(x, rightIndex, mid + 1, end);
}
// adds 1 to the height of the shortest trees > minHeight, for a maximum of quantity trees
void update(int quantity, int minHeight) {
int startIndex = lowerBound(minHeight);
if (startIndex >= n) return;
int maxHeight = getValue(startIndex + quantity - 1);
int maxStartIndex = lowerBound(maxHeight);
int maxEndIndex = lowerBound(maxHeight + 1) - 1;
updateRange(startIndex, maxStartIndex - 1);
int updated = maxStartIndex - startIndex;
int remaining = quantity - updated;
updateRange(std::max(maxEndIndex - remaining + 1, maxStartIndex), maxEndIndex);
debug("maxHeight: %d\n", maxHeight);
debug("updated: %d\n", updated);
debug("remaining: %d\n", remaining);
debug("updateRange(%d, %d)\n", startIndex, maxStartIndex - 1);
debug("updateRange(%d, %d)\n", maxEndIndex - remaining + 1, maxEndIndex);
}
void print(int index = 0, int start = 0, int end = -1) {
if (end == -1) end = n - 1;
if (start == end) {
printf("%d, ", nodes[index].height);
return;
}
int leftIndex = 2 * index + 1;
int rightIndex = leftIndex + 1;
int mid = (start + end) / 2;
nodes[index].propagate(&nodes[leftIndex], &nodes[rightIndex]);
print(leftIndex, start, mid);
print(rightIndex, mid + 1, end);
if (index == 0) printf("\n");
}
}
int main() {
scanf("%d %d", &n, &queries);
for (int i = 0; i < n; i++) {
scanf("%d", &input[i]);
}
std::sort(input, input + n);
SegmentTree::build();
// SegmentTree::print();
for (int q = 0; q < queries; q++) {
char c;
int x, y;
scanf(" %c %d %d", &c, &x, &y);
if (c == 'F') {
SegmentTree::update(x, y);
// SegmentTree::print();
} else if (c == 'C') {
int answer = SegmentTree::query(x, y);
printf("%d\n", answer);
}
}
}
Compilation message
grow.cpp: In function 'int SegmentTree::getValue(int, int, int, int)':
grow.cpp:182:5: warning: control reaches end of non-void function [-Wreturn-type]
182 | }
| ^
grow.cpp: In function 'int main()':
grow.cpp:228:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
228 | scanf("%d %d", &n, &queries);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~
grow.cpp:231:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
231 | scanf("%d", &input[i]);
| ~~~~~^~~~~~~~~~~~~~~~~
grow.cpp:244:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
244 | scanf(" %c %d %d", &c, &x, &y);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
1055 ms |
9556 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
5 ms |
8140 KB |
Output is correct |
2 |
Correct |
6 ms |
8172 KB |
Output is correct |
3 |
Correct |
6 ms |
8144 KB |
Output is correct |
4 |
Correct |
5 ms |
8140 KB |
Output is correct |
5 |
Correct |
61 ms |
9164 KB |
Output is correct |
6 |
Correct |
97 ms |
9388 KB |
Output is correct |
7 |
Correct |
34 ms |
8140 KB |
Output is correct |
8 |
Correct |
41 ms |
8864 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
83 ms |
9440 KB |
Output is correct |
2 |
Correct |
258 ms |
9472 KB |
Output is correct |
3 |
Correct |
47 ms |
8204 KB |
Output is correct |
4 |
Correct |
52 ms |
9116 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
277 ms |
9660 KB |
Output is correct |
2 |
Correct |
137 ms |
9444 KB |
Output is correct |
3 |
Correct |
154 ms |
8388 KB |
Output is correct |
4 |
Correct |
194 ms |
9492 KB |
Output is correct |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
1064 ms |
9668 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
1073 ms |
9768 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
1082 ms |
9596 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
1041 ms |
9672 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
1066 ms |
9928 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Correct |
402 ms |
11312 KB |
Output is correct |