文章标题 CSU 1838: Water Pump (单调栈)
2017-04-19 15:56
381 查看
1838: Water Pump
链接 1838: Water Pump题意:给出n堵墙(水坝?),已知各个墙的高度hi。 这些墙之间灌满了水,当然这些水都是符合 物理规律的,即不会漂浮在空中。然后问如 果在两堵墙之间开一个洞,那么最多可以流 出多少水?
分析:要求出第i堵墙和i+1堵墙流出的水量,可以计算出左边的前缀和面积dpl[i],然后计算右边的后缀和面积dpr[i],然后用总面积减去两边的面积剩下的就是流出的水量。计算前后缀和用单调栈求,时间复杂度为O(n)
代码:
#include<iostream> #include<string> #include<cstdio> #include<cstring> #include<vector> #include<math.h> #include<stack> #include<map> #include<queue> #include<algorithm> using namespace std; const int inf = 0x3f3f3f3f; int n; int hi[100005]; int dpl[100005];//dpl[i]表示前i个水坝所能蓄的水 int dpr[100005];//dpr[i]表示i~n个水坝蓄的水 stack<pair<int,int> >st;//单调栈 (下降) int main () { int t; scanf ("%d",&t); while (t--){ while (st.size())st.pop(); scanf ("%d",&n); for (int i=1;i<=n;i++){ scanf ("%d",&hi[i]); } dpl[1]=0;//左边的前缀和 st.push(make_pair(hi[1],1)); int first,id; for (int i=2;i<=n;i++){ //如果栈顶的高度比当前的高度低就弹出 while (st.size()>1&&st.top().first<=hi[i]) st.pop(); first=st.top().first; id=st.top().second; if (st.size()==1){ if (hi[i]<first)dpl[i]=dpl[id]+min(first,hi[i])*(i-id);//如果栈只剩一个点,直接赋值 else { dpl[i]=dpl[id]+min(first,hi[i])*(i-id); st.pop();//如果当前的高度比最后一个还高的话,就将弹出去掉 } } else { dpl[i]=dpl[id]+(i-id)*hi[i]; } st.push(make_pair(hi[i],i));//放进栈中 } // for (int i=1;i<=n;i++){ // cout<<dpl[i]<<" "; // } // cout<<endl; dpr =0;//求右边的前缀和(后缀和) while (st.size()) st.pop(); st.push(make_pair(hi ,n)); for (int i=n-1;i>=1;i--){ while (st.size()>1&&st.top().first<=hi[i]) st.pop(); first=st.top().first; id=st.top().second; if (st.size()==1){ if (hi[i]<first){ dpr[i]=dpr[id]+min(hi[i],first)*(id-i); } else { dpr[i]=dpr[id]+min(hi[i],first)*(id-i); st.pop(); } } else { dpr[i]=dpr[id]+hi[i]*(id-i); } st.push(make_pair(hi[i],i)); } // for (int i=n;i>=1;i--){ // cout<<dpr[i]<<" "; // } // cout<<endl; int ans=0; int sum=dpl ; for (int i=1;i<=n-1;i++){ ans=max(ans,sum-(dpl[i]+dpr[i+1]));//用总面积减去两端的前后缀和就少第i个水坝流走的水量 } printf ("%d\n",ans); } return 0; }
相关文章推荐
- CSU-ACM 1838: Water Pump(单调栈+前缀后缀和)
- 文章标题 CSU 1834: Oil(欧拉路径)
- 文章标题 CSU 1845: Sensor network (暴力LCA+kruskal思想)
- 文章标题 CSU 1826: Languages(字符串的处理+map)
- 文章标题 CSU 1831: Found(矩阵快速幂)
- 文章标题 SPOJ - DRUIDEOI : Fata7y Ya Warda!(单调栈)
- 文章标题 CSU 1832: Jump(DP)
- 文章标题 CSU 1846: Assembly line(DP)
- 文章标题 CSU 1849: Comparing answers(矩阵降维+随机化思想)
- 文章标题 HDU 3410 : Passing the Message (单调栈)
- 文章标题 CSU 1578 : 爬楼梯 (简单DP)
- 文章标题 CSU 1756 :Prime
- 文章标题 CSU 1856: Sokoban(模拟)
- 文章标题 CSU 1859: Gone Fishing(贪心)
- 文章标题 csu1333 :Funny Car Racing(最短路 spfa)
- 文章标题 CSU 1913 (线段树+二分答案)
- 文章标题CSU 1862: The Same Game(模拟)
- 文章标题 CSU 1828 : Dictionary
- 文章标题 POJ 2559 : Largest Rectangle in a Histogram (单调栈)
- 文章标题 CSU 1963: Feed the rabbit (斜率DP优化)