单调栈(SOJ 2511)
SOJ 2511: Moooo http://acm.scu.edu.cn/soj/problem.action?id=2511
问题:给出$n$个元素$node[i], 0\le i<n$,每个元素$node[i]$有两个属性height和volume.对于每个$node[i]$,它的volume只能被两边height值比它的大并且离它最近的元素取得。求解可以取得最大volume的元素并输出最大的volume.
分析:对每个元素$node[i]$,我们只需找出从$i-1$到$0$(从$i+1$到$n-1$)中第一个height大于$node[i]$的height的元素$node[i']$($node[i'']$),这一点跟SOJ 3085类似(参考这里).
方法:维护一个单调递减栈。
代码:
#include<iostream>
#include<stack>
#include<cstring>
using namespace std;
struct node
{
int no;
int hgt;
int vol;
};
node cows[50005];
int volume[50005];
int main()
{
int N;
int i;
stack<node>s;
int ans;
while(scanf("%d",&N)==1)
{
for(i=0;i<N;i++)
{
scanf("%d%d",&cows[i].hgt,&cows[i].vol);
cows[i].no=i;
}
memset(volume,0,sizeof(volume));
for(i=0;i<N;i++)
{
while(!s.empty() && cows[i].hgt>s.top().hgt)
{
volume[i]+=s.top().vol;
s.pop();
}
if(!s.empty())
volume[s.top().no]+=cows[i].vol;
s.push(cows[i]);
}
while(!s.empty())
s.pop();
ans=0;
for(i=0;i<N;i++)
ans=volume[i]>ans ? volume[i] : ans;
printf("%d\n",ans);
}
return 0;
}