Để đơn giản hóa bài toán, ta tạm coi $w_i = 1$ với mọi $i$ (mình sẽ gọi mỗi đoạn trong đề bài là mỗi cột cho dễ tưởng tượng), và ta chỉ tính thời gian ngập của vị trí $i$ khi nước chảy ở ngay vị trí $i$. Để tính được thời gian vị trí $i$ bị ngập trong trường hợp này, ta làm như sau:
Gọi thời gian tính được là $orig(i)$ Bây giờ để tính ra được đáp án cần tìm, ta cần phải tính thời điểm mà bắt đầu nước chảy vào vị trí trong khoảng từ $prv_i+1$ đến $nxt_i$ (bạn có thể thử tưởng tượng quá trình nước chảy để hiểu tại sao ta chỉ cần tính thêm cái này). Gọi thời điểm này là $dp(i)$, và vị trí nước chảy vào đầu tiên là $x$, ta có:
Ta thấy phần tính $prv_i$ và $nxt_i$ có thể mất $O(N^2)$, còn phần $dp$ do có $n$ trạng thái, mỗi trạng thái chỉ "di chuyển" $O(1)$ lần nên độ phức tạp phần $dp$ chỉ là $O(n)$. Vì vậy ta cần tối ưu phần tính $prv_i$ và $nxt_i$.
Giả sử ta đang tính $prv_i$, ta cần thực hiện truy vấn tìm $j$ thỏa mãn $H_j > H_i$, $j < i$ và $j$ lớn nhất có thể.
Do đó ta có thuật toán tính $prv_i$ trong $O(N\log{N})$ như sau:
Phần tính $nxt_i$, ta cũng giải quyết tương tự
Đến đây mình nghĩ các bạn có thể tự suy nghĩ cách xử lí khi $w_i$ không bằng nhau rồi.
Tổng kết: Độ phức tạp tính toán $O(N\log{N} + N)$
Note: Code mẫu hơi dài do mình chưa tận dụng được con trỏ dành cho hàm của C++. Nếu bạn tận dụng được, code có thể còn ngắn hơn và giảm thiểu rủi ro bị lỗi khi code.