제출 #526657

#제출 시각아이디문제언어결과실행 시간메모리
526657LFFBGrowing Trees (BOI11_grow)C++14
40 / 100
1082 ms11312 KiB
#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); } } }

컴파일 시 표준 에러 (stderr) 메시지

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 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...