51Nod 算法马拉松28 C题 栈 单调队列
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - 51Nod1952
题意概括
有一个栈,有3种操作:
Ο 从栈顶加入一个元素
Ο 从栈底加入一个元素
Ο 从栈顶弹出一个元素
现在,求每次操作后栈内元素的最大值和mod (1e9+7)
n次操作,n<=1e7
题解
这题对于博主这样的蒟蒻,做出来了,万分欣喜。
我们在搞一个栈的同时,维护一个单调不降的队列。
然后在弹出栈的时候,如果队尾元素等于当前弹出的元素,那么队尾出队。
至于两种进队,都是最基础的维护队列的方法。
每次,最大值就是队尾元素值。
代码
#include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> using namespace std; typedef long long LL; const int N=1e7+5; const int mod=1e9+7; int n,a[N],b[N]; int q[N*2],head,tail,st[N*2],first,last; LL A,B,C,x,aa,bb,MOD; int main(){ scanf("%d%lld%lld%lld%lld%lld%lld%lld",&n,&A,&B,&C,&x,&aa,&bb,&MOD); for (int i=1,tot=0;i<=n;i++){ x=(x*aa+bb)%MOD; LL xx=x%(A+B+C); if (tot<=1||xx<A) a[i]=0,b[i]=x,tot++; else if (A<=xx&&xx<A+B) a[i]=1,b[i]=x,tot++; else a[i]=2,tot--; } head=1e7+2,tail=head; first=head,last=tail; int ans=0; for (int i=1;i<=n;i++){ if (a[i]==0){ st[++last]=b[i]; if (q[tail]<=b[i]) q[++tail]=b[i]; } else if (a[i]==1){ st[first--]=b[i]; while (head<tail&&q[head+1]<b[i]) head++; q[head--]=b[i]; } else { if (q[tail]==st[last]) tail--; last--; } ans=(ans+q[tail])%mod; } printf("%d",ans); return 0; }