【51Nod1952】栈-单调栈+单调队列

测试地址:
做法:本题需要用到单调栈+单调队列。
我们可以用一些高级数据结构O(nlogn)简易地算出这个结果,但是看到数据范围,知道我们必须要找一个O(n)的做法。
我们看既有插入又有删除的那一端,显然可以用一个单调栈来维护,单调栈内的元素从栈底到栈顶应该严格递增。
那么另一端我们怎么处理呢?我们发现,只有当上面的单调栈取完时,我们会删掉对另一端来说是尾端的一个元素,而插入和删除不在一端的数据结构显然是队列,启发我们用单调队列来维护另一端,单调队列里的元素从队首到队尾应该递减,但不是严格递减。
这样一来,求最大值时就将单调栈的栈顶和单调队列的队首比较一下即可,而删除一个元素时,首先删栈中的元素,当栈中没有元素时再删队列的队首。因为每个元素最多进队(栈)和出队(栈)一次,所以时间复杂度是O(n)的。
以下是本人代码:

#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;
}
posted @ 2018-04-17 17:56  Maxwei_wzj  阅读(108)  评论(0编辑  收藏  举报