http://acm.scu.edu.cn/soj/problem.action?id=2511
题意:每头牛都会发出叫声,然而这个叫声只会被离他最近的一个比他高的牛听到,当然这个叫声是双向传播的。
思路:
找出第一个比他高的,就可以维护一个从栈顶到栈底单调增的栈,每次每个元素要进栈之前就将栈中所有比他小的元素出栈,这样之后栈顶的元素就是第一个比他高的。也就是跟那个windy cake 类似,把当前元素当做最大值,找这个最长区间,区间的边界就是两边的第一个比他高的,找到以后将这个牛听到的声音加上传来的音量。 每个元素都要找第一个比他高的元素利用单调栈就将复杂度从O(n^2) 降到O(n)。
左右各做一次单调栈就好了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
#define M 100009
int n,h[M],v[M],ans[M];
int main()
{
while(scanf("%d",&n) == 1)
{
memset(ans,0,sizeof(ans));
for(int i = 0;i < n;i++) scanf("%d %d",&h[i],&v[i]);
stack<int> s;
int maxx = 0;
for(int i = 0;i < n;i++) //对于每个元素找左边第一个高的,从左到右做单调栈
{
while(!s.empty() && h[s.top()] < h[i]) s.pop();
if(!s.empty())
{
ans[s.top()] += v[i]; //第一个比他高的听到了这个声音
maxx = max(maxx,ans[s.top()]);
}
s.push(i);
}
while(!s.empty()) s.pop();
for(int i = n - 1;i >= 0;i--) //对于每个元素找右边第一个高的,从右到左做单调栈
{
while(!s.empty() && h[s.top()] < h[i]) s.pop();
if(!s.empty())
{
ans[s.top()] += v[i];
maxx = max(maxx,ans[s.top()]);
}
s.push(i);
}
printf("%d\n",maxx);
}
return 0;
}