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;
}

  

posted @ 2017-09-01 22:00  zzd233  阅读(503)  评论(0编辑  收藏  举报