Official

G - Home Garden Editorial by en_translator


As a straightforward solution, one can manage the plants and their hand naively. But this costs time complexity of \(O(Q^2)\), which is not fast. The bottleneck of this naive algorithm is the second type of query, which asks to increase the height of every plant by \(H\).

By managing the information of the plants properly, let us speed up the process of the query of the second type.

First, consider the property of the operations. We can observe that plants that were planted by earlier queries are higher. If we let \(A_i =\) ( the height of plant of the initially planted plant when up to the \(i\)-th query is processed, if it is not harvested ), then the height of the plant planted by the \(i\)-th query right before processing the \(j\)-th query is \(A_{j-1}-A_i\).

This \(A\) can be computed while processing the queries. If the \(i\)-th query is of the second type, then \(A_i=A_{i-1}+T\); otherwise, \(A_i=A_{i-1}\).

Finally, let us consider how to process the queries of first and third types. Instead of managing plants with their heights, let us do so with the indices of the queries where the plants were planted. Then the first type of query is an insertion, which can be processed easily. A query of the third type can be processed by scanning each plant in the order of their query indices, and harvesting it if it has a height of \(H\) or greater, and stop harvesting if less than \(H\). Since each plant is harvested only once, we harvest a plant at most \(Q\) times in total. Also, we inspect a plant that is not immediately harvested at most once per a query of the third type, for a total of \(Q\) times. Therefore, this can be processed in a total of \(O(Q)\) time.

When implementing, we can use a queue. Also, beware of overflows.

(WIP)

Sample code (C++)

#include <bits/stdc++.h>
using namespace std;

int main() {
    int q;
    cin >> q;
    queue<int> que;
    vector<long long> height(q + 1);
    height[0] = 0;
    for (int i = 0; i < q; ++i) {
        int t;
        cin >> t;
        if (t == 1) {
            height[i + 1] = height[i];
            que.push(i);
        }
        if (t == 2) {
            long long add;
            cin >> add;
            height[i + 1] = height[i] + add;
        }
        if (t == 3) {
            height[i + 1] = height[i];
            long long h;
            cin >> h;
            int ans = 0;
            while (!que.empty()) {
                if (height[i + 1] - height[que.front()] >= h) {
                    ans++;
                    que.pop();
                } else {
                    break;
                }
            }
            cout << ans << "\n";
        }
    }
}

posted:
last update: