洛谷-P11833.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include <algorithm>
  2. #include <cstdint>
  3. #include <iostream>
  4. #include <vector>
  5. using int64 = std::int64_t;
  6. class SegmentTree {
  7. public:
  8. explicit SegmentTree(const std::vector<int64>& values)
  9. : n_(static_cast<int>(values.size()) - 1),
  10. sum_(4 * n_ + 4), lazy_(4 * n_ + 4), has_lazy_(4 * n_ + 4, false) {
  11. minimum_.resize(4 * n_ + 4);
  12. maximum_.resize(4 * n_ + 4);
  13. build(1, 1, n_, values);
  14. }
  15. int64 range_sum(int left, int right) {
  16. if (left > right) return 0;
  17. return range_sum(1, 1, n_, left, right);
  18. }
  19. void range_assign(int left, int right, int64 value) {
  20. if (left <= right) range_assign(1, 1, n_, left, right, value);
  21. }
  22. int64 point_value(int position) {
  23. return range_sum(position, position);
  24. }
  25. // The maintained array is nondecreasing. Return n+1 if no value >= target.
  26. int first_at_least(int left, int64 target) {
  27. return first_at_least(1, 1, n_, left, target);
  28. }
  29. // Return 0 if no value <= target in [1, right].
  30. int last_at_most(int right, int64 target) {
  31. return last_at_most(1, 1, n_, right, target);
  32. }
  33. private:
  34. int n_;
  35. std::vector<int64> sum_;
  36. std::vector<int64> minimum_;
  37. std::vector<int64> maximum_;
  38. std::vector<int64> lazy_;
  39. std::vector<bool> has_lazy_;
  40. void apply(int node, int left, int right, int64 value) {
  41. sum_[node] = value * (right - left + 1);
  42. minimum_[node] = maximum_[node] = value;
  43. lazy_[node] = value;
  44. has_lazy_[node] = true;
  45. }
  46. void push(int node, int left, int right) {
  47. if (!has_lazy_[node] || left == right) return;
  48. int middle = (left + right) / 2;
  49. apply(node * 2, left, middle, lazy_[node]);
  50. apply(node * 2 + 1, middle + 1, right, lazy_[node]);
  51. has_lazy_[node] = false;
  52. }
  53. void build(int node, int left, int right, const std::vector<int64>& values) {
  54. if (left == right) {
  55. sum_[node] = values[left];
  56. minimum_[node] = maximum_[node] = values[left];
  57. return;
  58. }
  59. int middle = (left + right) / 2;
  60. build(node * 2, left, middle, values);
  61. build(node * 2 + 1, middle + 1, right, values);
  62. sum_[node] = sum_[node * 2] + sum_[node * 2 + 1];
  63. minimum_[node] = minimum_[node * 2];
  64. maximum_[node] = maximum_[node * 2 + 1];
  65. }
  66. int64 range_sum(int node, int left, int right, int query_left, int query_right) {
  67. if (query_left <= left && right <= query_right) return sum_[node];
  68. push(node, left, right);
  69. int middle = (left + right) / 2;
  70. int64 result = 0;
  71. if (query_left <= middle)
  72. result += range_sum(node * 2, left, middle, query_left, query_right);
  73. if (query_right > middle)
  74. result += range_sum(node * 2 + 1, middle + 1, right, query_left, query_right);
  75. return result;
  76. }
  77. void range_assign(int node, int left, int right, int query_left, int query_right,
  78. int64 value) {
  79. if (query_left <= left && right <= query_right) {
  80. apply(node, left, right, value);
  81. return;
  82. }
  83. push(node, left, right);
  84. int middle = (left + right) / 2;
  85. if (query_left <= middle)
  86. range_assign(node * 2, left, middle, query_left, query_right, value);
  87. if (query_right > middle)
  88. range_assign(node * 2 + 1, middle + 1, right, query_left, query_right, value);
  89. sum_[node] = sum_[node * 2] + sum_[node * 2 + 1];
  90. minimum_[node] = minimum_[node * 2];
  91. maximum_[node] = maximum_[node * 2 + 1];
  92. }
  93. int first_at_least(int node, int left, int right, int query_left, int64 target) {
  94. if (right < query_left || maximum_[node] < target) return n_ + 1;
  95. if (left == right) return sum_[node] >= target ? left : n_ + 1;
  96. push(node, left, right);
  97. int middle = (left + right) / 2;
  98. int result = first_at_least(node * 2, left, middle, query_left, target);
  99. if (result != n_ + 1) return result;
  100. return first_at_least(node * 2 + 1, middle + 1, right, query_left, target);
  101. }
  102. int last_at_most(int node, int left, int right, int query_right, int64 target) {
  103. if (left > query_right || minimum_[node] > target) return 0;
  104. if (left == right) return sum_[node] <= target ? left : 0;
  105. push(node, left, right);
  106. int middle = (left + right) / 2;
  107. int result = last_at_most(node * 2 + 1, middle + 1, right, query_right, target);
  108. if (result != 0) return result;
  109. return last_at_most(node * 2, left, middle, query_right, target);
  110. }
  111. };
  112. struct Box {
  113. int index;
  114. int64 deadline;
  115. int64 target_normalized;
  116. };
  117. int main() {
  118. std::ios::sync_with_stdio(false);
  119. std::cin.tie(nullptr);
  120. int test_point, test_cases;
  121. std::cin >> test_point >> test_cases;
  122. (void)test_point;
  123. while (test_cases--) {
  124. int n;
  125. std::cin >> n;
  126. std::vector<int64> normalized(n + 1);
  127. std::vector<Box> boxes(n);
  128. for (int i = 1; i <= n; ++i) {
  129. int64 initial, target, deadline;
  130. std::cin >> initial >> target >> deadline;
  131. normalized[i] = initial - i;
  132. boxes[i - 1] = {i, deadline, target - i};
  133. }
  134. std::sort(boxes.begin(), boxes.end(), [](const Box& lhs, const Box& rhs) {
  135. if (lhs.deadline != rhs.deadline) return lhs.deadline < rhs.deadline;
  136. return lhs.index < rhs.index;
  137. });
  138. SegmentTree tree(normalized);
  139. int64 elapsed = 0;
  140. bool possible = true;
  141. for (const Box& box : boxes) {
  142. int i = box.index;
  143. int64 current = tree.point_value(i);
  144. int64 target = box.target_normalized;
  145. if (current < target) {
  146. int first = tree.first_at_least(i, target);
  147. int right = first - 1;
  148. int64 old_sum = tree.range_sum(i, right);
  149. elapsed += target * (right - i + 1) - old_sum;
  150. tree.range_assign(i, right, target);
  151. } else if (current > target) {
  152. int last = tree.last_at_most(i, target);
  153. int left = last + 1;
  154. int64 old_sum = tree.range_sum(left, i);
  155. elapsed += old_sum - target * (i - left + 1);
  156. tree.range_assign(left, i, target);
  157. }
  158. if (elapsed > box.deadline) possible = false;
  159. }
  160. std::cout << (possible ? "Yes\n" : "No\n");
  161. }
  162. return 0;
  163. }