区间最大值-最小值的区间的个数

链接:https://ac.nowcoder.com/acm/contest/6874/I
来源:牛客网

题目描述

《无限的斯特拉托斯》又称之为名作之壁,其销量一直被圈内人士津津乐道。给你n个数字,第iii个数字a[i]表示名作之壁第i天的销量。若某段区间[l,r]中最大值和最小值之差大于k,则称该区间为畅销区间。请问一共有多少个区间为畅销区间?

输入描述:

第一行两个正整数n,k,其中n≤1e7k≤1e9

接下来一行三个正整数a[0],b,c,按照a[i]=(a[i−1]×b+c)%1e9的规则生成第1天到第nn天的销量,a[0]不算入区间计算,其中a[0],b,c≤1e9

输出描述:

输出畅销区间的个数。

示例1

输入

复制
4 1
1 1 1

输出

复制
3




这个题目的意思就是所找有多少个区间内的最大值-最小值>k的区间个数
对于维护区间内的最值那肯定是单调队列了

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
// 之差至少2 
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int maxn=1e7+100;
const int mod=1e9;
ll a[maxn];
ll qmax[maxn];
ll qmin[maxn];
int main(){
    int n;
    ll b,c,k;
    cin>>n>>k;
    cin>>a[0]>>b>>c;
    for(int i=1;i<=n;i++){
        a[i]=(1ll*a[i-1]*b+c)%mod;
    }
    ll ans=0,l=1,h1=1,t1=0,h2=1,t2=0;
    for(int i=1;i<=n;i++){
        while(h1<=t1&&a[i]>=a[qmax[t1]]) t1--;
        while(h2<=t2&&a[i]<=a[qmin[t2]]) t2--;
        qmax[++t1]=i;
        qmin[++t2]=i;
        while(h1<=t1&&h2<=t2&&a[qmax[h1]]-a[qmin[h2]]>k){
            ans+=n-i+1;//计算权值 
            l++;
            if(qmax[h1]<l) h1++;
            if(qmin[h2]<l) h2++;
        }
    } 
    cout<<ans<<endl;
} 

 



posted @ 2020-12-16 23:49  lipu123  阅读(533)  评论(0编辑  收藏  举报