51nod 1952 栈【单调队列】

Description

LYK有一个栈,众所周知的是这个数据结构的特性是后进先出的。

LYK感觉这样子不太美妙,于是它决定在这个前提下将其改进,也就是说,每次插入元素时,可以在栈顶或者栈底插入,删除元素时,只能在栈顶删除。

LYK想知道每次执行完操作后当前栈中元素的最大值是多少。

第一行一个数n表示操作次数。

接下来n行,每行两个数a。若a<=1,则接下来输入一个数b。

若a=0,则在栈顶插入一个数b。

若a=1,则在栈底插入一个数b。

若a=2,则在栈顶删除一个数。

每次操作后,输出当前栈中元素的最大值是多少。

保证任意时刻栈中至少含有一个数。

由于操作数实在太多了。

于是你可以采取这种方式读入所有操作。

读入8个参数n,A,B,C,x0,a,b,MOD。 0<=A,B,C<=100000,A+B+C>0,0<=x0,a,b<=10^9,1<=MOD<=10^9,1<=n<=10000000。

xi=(xi−1∗a+b)%MOD

对于第i次操作,若xi%(A+B+C)

题解

吐槽:读入太烦了。。。

从后面插入时,只有当大于栈顶才插入,从前面插入时,先把所有小于等于它的元素干掉再插入。同时再维护一个序号的栈,表示每个元素在栈中的位置,弹栈时如果值栈和序号栈的栈顶是同一个就弹,否则只弹序号栈。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 10000006
#define tt 1000000007
#define LL long long
using namespace std;
struct data{
    int x,id;
}que1[maxn*2];
int ans,A,B,C,M,x0,a,b,n,que2[maxn*2],hed1,tal1,hed2,tal2;
void push_front(LL x,int id){
    que2[--hed2]=id;
    while(hed1<=tal1&&que1[hed1].x<=x)hed1++;
    que1[--hed1].x=x;que1[hed1].id=id;
}
void push_back(LL x,int id){
    que2[++tal2]=id;
    if(x>que1[tal1].x)que1[++tal1].x=x,que1[tal1].id=id;
}
void pop(){
    if(que2[tal2]==que1[tal1].id)tal1--;
    tal2--;
}
int main(){
    freopen("stack.in","r",stdin);
    freopen("stack.out","w",stdout);
    scanf("%d%d%d%d%d%d%d%d",&n,&A,&B,&C,&x0,&a,&b,&M);
    hed1=hed2=maxn;tal1=tal2=maxn-1;
    for(int i=1;i<=n;i++){
        x0=((LL)x0*a%M+b)%M;
        if(x0%(A+B+C)<A||tal2<=hed2)push_back(x0,i);else
        if(A<=x0&&x0%(A+B+C)<A+B)push_front(x0,i);else pop();
        (ans+=que1[tal1].x)%=tt;
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/fyoier/article/details/78493028