# Solution : Free Contest 132 - Water
### Writer : SunnyYeahBoi - Minh Phương Vũ
Link : [Free Contest 132 - Water](https://oj.vnoi.info/problem/fc132_water)
### Để giải được bài toán ta chia thành 2 phần:
- **Phần 1 : Làm sao để tính được lượng nước với dãy h[i] cho trước?**
- Với một **h[i]** ta có thể dễ dàng nhận thấy, ô thứ **i** có chứa nước khi tồn tại một cột cao hơn **h[i]** ở bên trái của **i** và tương tự với bên phải của **i**.
- Để tính được lượng nước có tại ô thứ **i** ta làm như sau: với mỗi **h[i]**, ta đi tìm cột có độ cao lớn nhất về bên trái và độ cao lớn nhất về bên phải sau đấy lượng nước đọng lại tại ô thứ **i** sẽ bằng **min(h[j] , h[k]) - h[i]**
**(với h[j] = max(h[1]...h[i-1]) và h[k] = max(h[i+1]...h[n]) )**
- **Phần 2: Làm sao để tính được lượng nước tối đa tăng được với một **h[i]** khi nó tăng lên 1 đơn vị?**
- Với mỗi **h[i]**, lượng nước chỉ tăng chỉ khi chỉ tồn tại **duy nhất một phía trái hoặc phải có** h[j] cao hơn (với j khác i).
- Nếu **h[i]** thỏa mãn điều kiện trên, ta sẽ tính lượng nước tăng lên khi tăng **h[i]** lên 1 đơn vị.
- Ta có thể dễ dàng tính bằng cách: tìm cột **j** với **h[j]** > **h[i]** và **abs(j - i) là nhỏ nhất**
### Thanks For Reading ♥
# Code mẫu:
```c++
/*
Cred : SunnyYeahBoi
May Not Be The Smartest But Always Try My Best <3
*/
#include "bits/stdc++.h"
using namespace std;
//___Defines
#define TaskName "a"
#define FastInput() ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define FileInput() if(TaskName != ""){freopen(TaskName".inp" , "r" , stdin);freopen(TaskName".out" , "w" , stdout);}
#define int long long
#define endl "\n"
//___Constants
const double Pi = acos(-1.0);
const int INF = INT_MAX;
//___Structs
/*It's not empty ;-; what are u thinking about huh >:CCC*/
//___Variables
class Solution{
public:
int startAmount(int n , vector<int>& height){
vector<int> leftTallest(n) , rightTallest(n);
leftTallest[0] = height[0];
for(int i = 1 ; i < n ; i++)
leftTallest[i] = max(leftTallest[i-1] , height[i]);
rightTallest[n-1] = height[n-1];
for(int i = n-2 ; i >= 0 ; i--)
rightTallest[i] = max(rightTallest[i+1] , height[i]);
int res = 0;
for(int i = 1 ; i < n-1 ; i++){
if(height[i] > leftTallest[i-1] || height[i] > rightTallest[i+1])
continue;
res += min(leftTallest[i-1] , rightTallest[i+1]) - height[i];
}
return res;
}
int maximumIncreaseAfterOp(int n , vector<int>& height){
vector<int> q;
vector<int> leftmostBigger(n) , rightmostBigger(n);
for(int i = 0 ; i < n ; i++){
while(!q.empty() && height[q.back()] <= height[i])
q.pop_back();
if(q.empty()){
leftmostBigger[i] = -1;
}else leftmostBigger[i] = q.back();
q.push_back(i);
}
q.clear();
for(int i = n-1 ; i >= 0 ; i--){
while(!q.empty() && height[q.back()] <= height[i])
q.pop_back();
if(q.empty()){
rightmostBigger[i] = -1;
}else rightmostBigger[i] = q.back();
q.push_back(i);
}
q.clear();
int res = 0;
for(int i = 0 ; i < n ; i++){
if(leftmostBigger[i] > -1 && rightmostBigger[i] > -1)
continue;
int tmp = 0;
if(leftmostBigger[i] > -1)
tmp = i - leftmostBigger[i] - 1;
else tmp = rightmostBigger[i] - i - 1;
res = max(res , tmp);
}
return res;
}
};
void solve(){
int n;
cin >> n;
vector<int> a(n);
for(int i = 0 ; i < n ; i++) cin >> a[i];
Solution Sol;
cout << Sol.startAmount(n , a) + Sol.maximumIncreaseAfterOp(n , a) << endl;
}
int32_t main(){
//FileInput();// For Some Specific Problems
FastInput();// OMG It's OVER 9000 (⊙_⊙;)
int t = 1;
//cin >> t;
while(t--){// For Constructive Problems
solve();
}
return 0;
}
```