链接:https://ac.nowcoder.com/acm/contest/6874/I
来源:牛客网
题目描述
《无限的斯特拉托斯》又称之为名作之壁,其销量一直被圈内人士津津乐道。给你n个数字,第iii个数字a[i]表示名作之壁第i天的销量。若某段区间[l,r]中最大值和最小值之差大于k,则称该区间为畅销区间。请问一共有多少个区间为畅销区间?
输入描述:
第一行两个正整数n,k,其中n≤1e7,k≤1e9。
接下来一行三个正整数a[0],b,c,按照a[i]=(a[i−1]×b+c)%1e9的规则生成第1天到第nn天的销量,a[0]不算入区间计算,其中a[0],b,c≤1e9。
输出描述:
输出畅销区间的个数。
示例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; }