单调栈 51nod 1962 区间计数

本文介绍了一种使用两个单调栈解决复杂数据结构问题的方法,通过维护从大到小的单调队列并同步更新,实现了在元素出栈时计算最大矩形区间的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1962
这道题谢了很久的;
但是很高兴最后还是调出来了;
虽然我的单调栈是没有写错的;
但是光会模板显然是没有什么用的;
这道题目我们维护两个单调栈;
都是从大到小的;
两个单调队列需要同时更新;
什么时候统计答案呢?
当一个元素要出栈的时候,我们可以计算出这个最大值的区间;
那么我们在另外一个栈里找到这个值,爷计算出最大区间;
那么我们算算l可取的范围,r可取的范围,直接计算答案就好了;

#include<bits/stdc++.h>
#define Ll long long
using namespace std;
const int N=4e5+5;
int a[N][2],q[N][2],r[2];
int n,x,y;
Ll ans;
Ll out(int c,int v,int x,int y,int k){
    int L=1,R=r[k],mid,ans=1e9;
    while(R>=L){
        mid=L+R>>1;
        if(a[q[mid][k]][k]==v){ans=mid;break;}
        if(a[q[mid][k]][k]>v)L=mid+1;else R=mid-1;
    }
    if(ans==1e9)return 0;
    return (Ll)max(min(c,q[ans][k])-max(x*1ll,q[ans-1][k]+1ll)+1,0ll)*(y-max(c,q[ans][k])+1);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i][0]);
    for(int i=1;i<=n;i++)scanf("%d",&a[i][1]);
    r[1]=r[0]=q[1][0]=q[1][1]=1;
    for(int i=2;i<=n;i++)
        for(int j=0;j<=1;j++){
            while(r[j]&&a[q[r[j]][j]][j]<=a[i][j])ans+=out(q[r[j]][j],a[q[r[j]][j]][j],q[r[j]-1][j]+1,i-1,j^1),r[j]--;
            q[++r[j]][j]=i;
        }
    for(int i=1;i<=r[0];i++)ans+=out(q[i][0],a[q[i][0]][0],q[i-1][0]+1,n,1);
    printf("%lld",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值