P1901 ,P1823单调栈
以找到左边第一个大于它的数为例:
大致意思就是:
一个数 A 的左边第一个最大数 Q 确定后,对于下一个数 B
Q_ _ _ _ _ _A B
如果 A > B ,
那 B 左边第一个大的数就是 A ,
如果 A <= B , 那就说明:包括 A 在内的,从 B 到 Q 的所有数都比 B 小,则 B 左边一个的大的数就是 Q
由此可得到代码:(具体有两种写法,在下面两个代码中分别展示)
for(int i=1;i<=n;i++){
____while(arr[s.top()]<=arr[i]) s.pop();
____res[i]=arr[s.top()]
____s.push(i)
}
因为 Q 和 A 中间所有比 A 小的数都被删除了,所以栈是单调减的
以此为基础得到P1901代码:
P1901 AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
LL n,h[1000010],e[1000010],res[1000010],ans;
stack<LL> s;
int main() {
s.push(0);
h[0]=LLONG_MAX;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>h[i]>>e[i];
}
for(int i=1;i<=n;i++)
{
while(h[s.top()]<=h[i]) s.pop();
res[s.top()]+=e[i];
s.push(i);
}
while(!s.empty()) s.pop();
h[n+1]=LLONG_MAX;
s.push(n+1);
for(int i=n;i>=1;i--)
{
while(h[s.top()]<=h[i]) s.pop();
res[s.top()]+=e[i];
s.push(i);
}
sort(res+1,res+1+n);
cout<<res[n];
return 0;
}
对于P1823
因为栈中所有数是递减的,所以新的 heigh 来到时,在 pop 停止前的所有数都能和它对望,而原数列中被删除的数 E ,因为肯定小于栈中的一个数 W,所以有 E < W <= heigh , E 和 heigh 无法对望,故不会影响计数,
同时,因为等高的栈中数也会被删除,而登高的 W W height 也能对望,故要想办法统计与 heigh 登高的栈中数,可以使用 pair( heigh ,times )
P1823 AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long int LL;
typedef pair<LL,LL> par;
LL n,h,ans;
stack<par> s;
int main() {
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>h;
par p(h,1);
while(!s.empty()&&s.top().first<=h)
{
ans+=s.top().second;
if(s.top().first==h) p.second+=s.top().second;
s.pop();
}
if(!s.empty()) ans++;
s.push(p);
}
cout<<ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架