1. 程式人生 > 實用技巧 >1574. 接雨水 AcWing

1574. 接雨水 AcWing

原題連結

單調棧:

如果有凹陷處,那麼雨水=左邊的第一個單調上升最大的與右邊單調上升最大的取最小值與當前高度做差,思路很像單調棧,我們需要找到凹陷處,即需要用棧吞入比當前棧

頂小的值,如果遇到比它的值就停下,儲存當前棧頂下標(方便計算寬度),這是按行計算的,當計算完畢後,不能將左邊的圓柱pop,因為我們還需要計算以它為底作雨水容器的體積,當棧空或者拿比右邊的圓柱還大的圓柱作底就停下來.最後要將右圓柱入棧

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int h[100010];
 4 stack<int> s;
5 int main() 6 { 7 // freopen("in.txt","r",stdin); 8 int n,sum = 0; 9 scanf("%d",&n); 10 for(int i=1;i<=n;i++){ 11 scanf("%d",&h[i]); 12 if(s.empty()||h[i]<=h[s.top()]) { s.push(i); continue;} 13 while(!s.empty()&&h[s.top()]<h[i]){ 14 int
t = s.top(); 15 s.pop(); 16 if(s.empty()) break; 17 int wid = i-s.top()-1; 18 sum+=(min(h[i],h[s.top()])-h[t])*wid; 19 } 20 s.push(i); 21 } 22 printf("%d\n",sum); 23 }
單調棧

雙指標:

指標移動需要讓小的指標先移動,這樣才能逼近最大的圓柱,邊走變更新最值,只有當從高處到低處的時候,我們才需要+ans

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5+10;
 4 int l[N],r[N],h[N],ans;
 5 int main()
 6 { 
 7     int n;
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i++) scanf("%d",&h[i]);
10     int left = 0,right = n,lmax = h[0],rmax = h[n];//讓小的先移動逼近最大值
11     while(left<=right){
12         lmax = max(h[left],lmax);
13         rmax = max(h[right],rmax);
14         if(lmax<rmax){
15             ans += lmax-h[left];
16             left++;
17         }else{
18             ans += rmax-h[right];
19             right--;
20         } 
21     }
22     printf("%d\n",ans);
23 }
雙指標