您的位置:首页 > 其它

文章标题 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: