测试地址:栈
做法:本题需要用到单调栈+单调队列。
我们可以用一些高级数据结构简易地算出这个结果,但是看到数据范围,知道我们必须要找一个的做法。
我们看既有插入又有删除的那一端,显然可以用一个单调栈来维护,单调栈内的元素从栈底到栈顶应该严格递增。
那么另一端我们怎么处理呢?我们发现,只有当上面的单调栈取完时,我们会删掉对另一端来说是尾端的一个元素,而插入和删除不在一端的数据结构显然是队列,启发我们用单调队列来维护另一端,单调队列里的元素从队首到队尾应该递减,但不是严格递减。
这样一来,求最大值时就将单调栈的栈顶和单调队列的队首比较一下即可,而删除一个元素时,首先删栈中的元素,当栈中没有元素时再删队列的队首。因为每个元素最多进队(栈)和出队(栈)一次,所以时间复杂度是的。
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
int n,top,h,t,q[10000010],st[10000010];
int posq[10000010],posst[10000010],totq=0,totst=0,qhead=0;
ll A,B,C,x0,a,b,MOD,ans=0;
int main()
{
scanf("%d%lld%lld%lld%lld%lld%lld%lld",&n,&A,&B,&C,&x0,&a,&b,&MOD);
ll x=x0;
top=t=0;h=1;
for(int i=1;i<=n;i++)
{
x=(x*a+b)%MOD;
if (x%(A+B+C)<A||(totst+totq-qhead)<=1)
{
totst++;
if (!top||st[top]<x)
{
st[++top]=x;
posst[top]=totst;
}
}
else if (x%(A+B+C)<A+B)
{
totq++;
while(h<=t&&q[t]<x) t--;
q[++t]=x;
posq[t]=totq;
}
else
{
if (top)
{
totst--;
while(top&&posst[top]>totst) top--;
}
else
{
qhead++;
while(h<=t&&posq[h]<=qhead) h++;
}
}
int now=0;
if (h<=t) now=max(now,q[h]);
if (top) now=max(now,st[top]);
ans=(ans+(ll)now)%mod;
}
printf("%lld",ans);
return 0;
}