杭电多校第三次 Problem A. Ascending Rating(单调队列)

【题意】
给你一个长为n的数组a
让你对于每个长度为m的窗口。
算出其中的最大值以及从左往右遍历的时候这个最大值更新的次数。
【题解】
单调队列。
从后往前滑动窗口。
会发现我们维护以这个窗口里面的值为元素的单调队列的时候。
这个单调队列的长度就是最大值更新的次数。
因为我们把a[i]加入队列的时候。
队列尾巴上,小于等于这个a[i]的元素都会被删掉.
每个都这么做的话。
队列里面的元素就和更新时候的元素对应。
最大值就是队列的头部。


#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define pii pair<ll,ll>
using namespace std;
const int maxn=10000005;
ll nex[maxn],a[maxn],qq[maxn],t;
ll p,q,r,mo,ans,cnt,j,ctt,n,m,k,i,ma,ct,kk;
int main()
{
    ll T;
    scanf("%lld",&T);
    while(T--)
    {
        i=1;
        scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&k,&p,&q,&r,&mo);
        while(i<=n)
        {
            if(i<=k) scanf("%lld",&a[i]);
            else a[i]=(p*a[i-1]+q*i+r)%mo;
            i++;
        }
        ans=cnt=0;
        for(ll h=1,t=0,i=n;i;i--)
        {
            while(h<=t&&a[qq[t]]<=a[i]) t--;
            qq[++t]=i;
            if(i<=n-m+1)
            {
                while(qq[h]>=i+m) h++;
                ans+=(i^a[qq[h]]);
                cnt+=(i^(t-h+1));
            }
        }
        printf("%lld %lld\n",ans,cnt);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ffgcc/article/details/81324902