#include <algorithm>
#include <iostream>
#include <stack>
using namespace std;
struct Mowing {
Mowing(int64_t when, int64_t height, int maxIndex)
: when(when), height(height), maxIndex(maxIndex) {}
int64_t when, height;
int maxIndex;
};
const int MAXN = 500009;
int n, m, maxIndex;
int64_t when, height, result;
int64_t growth[MAXN], growthPrefixRaw[MAXN];
int64_t* growthPrefix = growthPrefixRaw + 1;
stack<Mowing> lastMowings;
void initialize() {
ios_base::sync_with_stdio(false);
cin >> n >> m;
growthPrefix[-1] = 0;
for (int i = 0; i < n; i++) {
cin >> growth[i];
}
sort(growth, growth + n, std::greater<int64_t>());
for (int i = 0; i < n; i++) {
growthPrefix[i] = growthPrefix[i - 1] + growth[i];
}
lastMowings.push(Mowing(0, 0, n - 1));
}
int binSearch(int down, int up) {
const auto& lastMowing = lastMowings.top();
while (up > down) {
int middle = (down + up + 1) / 2;
if (lastMowing.height + (when - lastMowing.when) * growth[middle] >= height) {
down = middle;
} else {
up = middle - 1;
}
}
return down;
}
int64_t growthInterval(int down, int up) {
return growthPrefix[up] - growthPrefix[down - 1];
}
void computeMaxIndex() {
if (lastMowings.empty()) {
return;
}
const auto& lastMowing = lastMowings.top();
int newMaxIndex = binSearch(maxIndex, lastMowing.maxIndex);
result += growthInterval(maxIndex + 1, newMaxIndex) * (when - lastMowing.when);
result -= (newMaxIndex - maxIndex) * (height - lastMowing.height);
maxIndex = newMaxIndex;
}
int main() {
initialize();
while (m--) {
cin >> when >> height;
result = 0;
maxIndex = -1;
while (!lastMowings.empty() &&
height < lastMowings.top().height) {
const auto& lastMowing = lastMowings.top();
int newMaxIndex = lastMowing.maxIndex;
result += growthInterval(maxIndex + 1, newMaxIndex) * (when - lastMowing.when);
result -= (newMaxIndex - maxIndex) * (height - lastMowing.height);
maxIndex = newMaxIndex;
lastMowings.pop();
}
computeMaxIndex();
while (!lastMowings.empty() &&
maxIndex == lastMowings.top().maxIndex) {
lastMowings.pop();
computeMaxIndex();
}
if (maxIndex >= 0) {
lastMowings.push(Mowing(when, height, maxIndex));
}
cout << result << endl;
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #include <algorithm> #include <iostream> #include <stack> using namespace std; struct Mowing { Mowing(int64_t when, int64_t height, int maxIndex) : when(when), height(height), maxIndex(maxIndex) {} int64_t when, height; int maxIndex; }; const int MAXN = 500009; int n, m, maxIndex; int64_t when, height, result; int64_t growth[MAXN], growthPrefixRaw[MAXN]; int64_t* growthPrefix = growthPrefixRaw + 1; stack<Mowing> lastMowings; void initialize() { ios_base::sync_with_stdio(false); cin >> n >> m; growthPrefix[-1] = 0; for (int i = 0; i < n; i++) { cin >> growth[i]; } sort(growth, growth + n, std::greater<int64_t>()); for (int i = 0; i < n; i++) { growthPrefix[i] = growthPrefix[i - 1] + growth[i]; } lastMowings.push(Mowing(0, 0, n - 1)); } int binSearch(int down, int up) { const auto& lastMowing = lastMowings.top(); while (up > down) { int middle = (down + up + 1) / 2; if (lastMowing.height + (when - lastMowing.when) * growth[middle] >= height) { down = middle; } else { up = middle - 1; } } return down; } int64_t growthInterval(int down, int up) { return growthPrefix[up] - growthPrefix[down - 1]; } void computeMaxIndex() { if (lastMowings.empty()) { return; } const auto& lastMowing = lastMowings.top(); int newMaxIndex = binSearch(maxIndex, lastMowing.maxIndex); result += growthInterval(maxIndex + 1, newMaxIndex) * (when - lastMowing.when); result -= (newMaxIndex - maxIndex) * (height - lastMowing.height); maxIndex = newMaxIndex; } int main() { initialize(); while (m--) { cin >> when >> height; result = 0; maxIndex = -1; while (!lastMowings.empty() && height < lastMowings.top().height) { const auto& lastMowing = lastMowings.top(); int newMaxIndex = lastMowing.maxIndex; result += growthInterval(maxIndex + 1, newMaxIndex) * (when - lastMowing.when); result -= (newMaxIndex - maxIndex) * (height - lastMowing.height); maxIndex = newMaxIndex; lastMowings.pop(); } computeMaxIndex(); while (!lastMowings.empty() && maxIndex == lastMowings.top().maxIndex) { lastMowings.pop(); computeMaxIndex(); } if (maxIndex >= 0) { lastMowings.push(Mowing(when, height, maxIndex)); } cout << result << endl; } } |
English